#include "simulate.h"
#include <cassert>
#include <new>
#include <malloc.h>
#include <algorithm>
#include <map>
//#include <time.h>
#include <sys/time.h>


int EL;
float err1;
int tsw1,tsw2;
int THREAD_NUM_T = 16;
double tot_vic_length;
extern double my_lambda;
extern int trace_size;

#ifndef PLACEMENT_INFO
//#define PLACEMENT_INFO
#endif

Simulate::~Simulate(void){
	passiveGates.clear();	
}


void Simulate::initPruning()
{
        for(int i=0; i<Ci->signalSize(); ++i)
                Ci->getSignal(i)->pruned = 0;
}


void Simulate::initMultithread_GREEDY(int thread_num){
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                Ci->getSignal(i)->MulTTraced.clear();
                for(int j = 0; j < thread_num; j++)
                        if(Ci->getSignal(i)->selected == 0)
                                Ci->getSignal(i)->MulTTraced[j] = false;
                        else
                                Ci->getSignal(i)->MulTTraced[j] = true;
        }
        
}


void Simulate::initMultithread_PRUNE(int thread_num){
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                Ci->getSignal(i)->MulTTraced.clear();
                for(int j = 0; j < thread_num; j++)
                        Ci->getSignal(i)->MulTTraced[j] = false;
        }
        
        for(int i=0; i<Ci->flipflopSize(); ++i){
                for(int j = 0; j < thread_num; j++)
                        if(Ci->getFlipflop(i)->getOutput(0)->pruned == 0)
                                Ci->getFlipflop(i)->getOutput(0)->MulTTraced[j] = true;
                        else
                                Ci->getFlipflop(i)->getOutput(0)->MulTTraced[j] = false;
        }        
}


void Simulate::initMultThread(int thread_num){

        sim_round = 0;
        //sigList.clear();
        //sigList.reserve(thread_num);
        //sigList.resize(thread_num);
        //CurSig.clear();
        //CurSig.reserve(thread_num);
        //CurSig.resize(thread_num);
        sigList = new SG[thread_num]; 
        CurSig = new Signal*[thread_num];
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                //This part if adding the control inputs or not for measure SRR
                if(Ci->getSignal(i)->untouchible == true)
                {
                        for(int j = 0; j < thread_num; j++)
                        {
                                myDataType f,g;
                                //if(Ci->getSignal(i)->valArray[0] == 0)
                                if(Ci->getSignal(i)->getVal() == 0)
                                {
                                        f.assign((BIT_TYPE)0);
                                        g = f;
                                        Ci->getSignal(i)->Mult_Val0[j] = f;
                                        Ci->getSignal(i)->Mult_Val1[j] = f;
                                        continue;
                                }
                                
                                f.assign((BIT_TYPE)1);
                                g = f;
                                for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); k++)
                                {
                                        f = f << 1;
                                        f = f | g;
                                }
                                
                                Ci->getSignal(i)->Mult_Val0[j] = f;
                                Ci->getSignal(i)->Mult_Val1[j] = f;
                        }
                        
                        continue;
                }
              
                for(int j = 0; j < thread_num; j++)
                {
                        myDataType f,g;
                        f.assign((BIT_TYPE)1);
                        g = f;
                        for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); k++)
                        {
                                f = f << 1;
                                f = f | g;
                        }
                        
                        Ci->getSignal(i)->Mult_Val0[j].assign((BIT_TYPE)0);
                        Ci->getSignal(i)->Mult_Val1[j] = f;
                }
                
                Ci->getSignal(i)->chosen = false;
        }
}


void Simulate::initACCMultThread(int thread_num, int seed_num){

        sim_round = 0;
        //sigList.clear();
        //sigList.reserve(thread_num);
        //sigList.resize(thread_num);
        //CurSig.clear();
        //CurSig.reserve(thread_num);
        //CurSig.resize(thread_num);
        sigList = new SG[thread_num]; 
        CurSig = new Signal*[thread_num];
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                for(int j = 0; j < thread_num; j++)
                {
                        if(Ci->getSignal(i)->getTraced(j) == true)
                                continue;                        
                        
                        Ci->getSignal(i)->Mult_Val0[j] = Ci->getSignal(i)->Mult_Val0_ref[seed_num];
                        Ci->getSignal(i)->Mult_Val1[j] = Ci->getSignal(i)->Mult_Val1_ref[seed_num];
                }
                
                Ci->getSignal(i)->chosen = false;
        }
}


void Simulate::initACCMultThread_MM(int thread_num, int seed_num, int mode_id){

        sim_round = 0;
        //sigList.clear();
        //sigList.reserve(thread_num);
        //sigList.resize(thread_num);
        //CurSig.clear();
        //CurSig.reserve(thread_num);
        //CurSig.resize(thread_num);
        sigList = new SG[thread_num]; 
        CurSig = new Signal*[thread_num];
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                for(int j = 0; j < thread_num; j++)
                {
                        if(Ci->getSignal(i)->getTraced(j) == true)
                                continue;                        
                        
                        Ci->getSignal(i)->Mult_Val0[j] = Ci->getSignal(i)->Mult_Val0_ref_MM[seed_num][mode_id];
                        Ci->getSignal(i)->Mult_Val1[j] = Ci->getSignal(i)->Mult_Val1_ref_MM[seed_num][mode_id];
                }
                
                Ci->getSignal(i)->chosen = false;
        }
}


void Simulate::initSimulateHybrid(){
        
	for(int i=0; i<Ci->signalSize(); ++i){
                
                if(Ci->getSignal(i)->getTraced() == false && Ci->getSignal(i)->untouchible == false) //KEY!!!
                {
                        Ci->getSignal(i)->setVal(Z);
                        Ci->getSignal(i)->setFlag0(0);
                        Ci->getSignal(i)->setFlag1(0);
                }
                
                Ci->getSignal(i)->stored = 0;//should not be here
                //if(Ci->getSignal(i)->getName() == "O1")
                //cout << "KUKUKU " << Ci->getSignal(i)->getVal() <<endl;
                
        }
        
        for(int i=0; i<Ci->gateSize(); ++i){
                Ci->getGate(i)->backRestored = false;
                Ci->getGate(i)->forceRestored = false;
        }
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                Ci->getFlipflop(i)->backRestored = false;
                Ci->getFlipflop(i)->forceRestored = false;
        }
}


void Simulate::initSimulate(bool a){
	for(int i=0; i<Ci->signalSize(); ++i){
		Ci->getSignal(i)->setVal(Z);
                Ci->getSignal(i)->setFlag0(0);
		Ci->getSignal(i)->setFlag1(0);
	}
	for(int i=0; i<Ci->flipflopSize(); ++i)
		Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
}


void Simulate::initSimulate(void){
	
        const int interval = SIM_CYCLE_NUM;
        for(int i=0; i<Ci->signalSize(); ++i){
                
                Ci->getSignal(i)->preset = false;
                Ci->getSignal(i)->untouchible = false;
		Ci->getSignal(i)->setVal(Z);
		Ci->getSignal(i)->val = Z;
		Ci->getSignal(i)->sw = 0;
		Ci->getSignal(i)->sw1 = 0;
		Ci->getSignal(i)->setFlag0(0);
		Ci->getSignal(i)->setFlag1(0);
                Ci->getSignal(i)->pruned = 0;
                Ci->getSignal(i)->selected = 0;
                Ci->getSignal(i)->stored = 0;
                
                Ci->getSignal(i)->valArray = new Value[interval];
                for(int j = 0; j < interval; j++)
                        Ci->getSignal(i)->valArray[j] = Z;
	}
        
	for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                Ci->getFlipflop(i)->getOutput(0)->Cur_P = 0.0;
                Ci->getFlipflop(i)->getOutput(0)->Cur_P0 = 0.0;
                Ci->getFlipflop(i)->getOutput(0)->Cur_P1 = 0.0;
		Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
        }
        
        //de-assert the control inputs
        string ctrInput;
        string val;
        while(1)
        {
                cout<<"Input the name for the deasserted signal"<<endl;
                cin >> ctrInput;
                
                if(ctrInput == "end")
                        break;
                
                cout<<"Input the value for the deasserted signal"<<endl;
                cin >> val;
                
                for(int i=0; i<Ci->signalSize(); ++i){
                        if(Ci->getSignal(i)->getName() == ctrInput)
                        {
                                Ci->getSignal(i)->untouchible = true;
                                Value v = (Value)atoi(val.c_str());
                                Ci->getSignal(i)->setVal(v);
                                for(int j = 0; j < interval; j++)
                                        Ci->getSignal(i)->valArray[j] = v;
                        }
                }
        }        
}


void Simulate::initSimulate(string filename){
	
        const int interval = SIM_CYCLE_NUM;
        for(int i=0; i<Ci->signalSize(); ++i){
                
                Ci->getSignal(i)->preset = false;
                Ci->getSignal(i)->untouchible = false;
		Ci->getSignal(i)->setVal(Z);
		Ci->getSignal(i)->val = Z;
		Ci->getSignal(i)->sw = 0;
		Ci->getSignal(i)->sw1 = 0;
		Ci->getSignal(i)->setFlag0(0);
		Ci->getSignal(i)->setFlag1(0);
                Ci->getSignal(i)->pruned = 0;
                Ci->getSignal(i)->selected = 0;
                Ci->getSignal(i)->stored = 0;
                
                //open for check SRR_GRR
                Ci->getSignal(i)->valArray = new Value[interval];
                //for(int j = 0; j < interval; j++)
                //Ci->getSignal(i)->valArray[j] = Z;
	}
        
	for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                Ci->getFlipflop(i)->getOutput(0)->Cur_P = 0.0;
                Ci->getFlipflop(i)->getOutput(0)->Cur_P0 = 0.0;
                Ci->getFlipflop(i)->getOutput(0)->Cur_P1 = 0.0;
                //The below line is the major difference from other "initsim" function
		Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
        }        
}


void Simulate::setResets(void){
	for(int i=0; i<Ci->flipflopSize(); ++i)
		Ci->getFlipflop(i)->getInput(2)->setVal(One);
	
	for(int i=0; i<Ci->signalSize(); ++i)
		if(Ci->getSignal(i)->getName()[0]=='R')
			Ci->getSignal(i)->setVal(One);
	return;
}


void Simulate::setSigValues(vector<Signal *> sigs, vector<Value> vals){
	for(unsigned i=0; i<sigs.size(); ++i)
		sigs[i]->setVal(vals[i]);
}


void Simulate::setTraceValues(vector<Value> vals){
	for(unsigned i=0; i<tracedSigs.size(); ++i)
		tracedSigs[i]->setVal(vals[i]);
}


void Simulate::initGates(void){
	for(int i=0; i<Ci->gateSize(); ++i){
		Ci->getGate(i)->setVisited(false);
		Ci->getGate(i)->setBackwardVisited(false);
		Ci->getGate(i)->passive = false;
	}
	for(int i=0; i<Ci->flipflopSize(); ++i){
		Ci->getFlipflop(i)->setVisited(false);
		Ci->getFlipflop(i)->setBackwardVisited(false);
	}
	return;
}


bool Simulate::PrintSignalBitVal(Signal* sig, int Tid)
{
        const int bit_num = 8 * sizeof(BIT_TYPE);
        const int check_highest_bits = TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE));
        cout<<"For signal "<<sig->getName()<<endl;
        for(int i = 0; i < TRACE_DEPTH_NUM; i++)
        {
                for(int j = 0; j < 8 * sizeof(BIT_TYPE); j++)
                {
                        BIT_TYPE temp1 = sig->Mult_Val0[Tid].bits[i];
                        BIT_TYPE temp2 = sig->Mult_Val1[Tid].bits[i];

                        temp1 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                        temp1 >>= bit_num - 1 - j;
                        
                        temp2 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                        temp2 >>= bit_num - 1 - j;
                        
                        
                        if(temp1 == temp2)
                                cout<<temp1;
                        else
                                cout<<"X";
                }
        }
        cout<<endl;
}


bool Simulate::PrintMyDataType(myDataType f)
{
        for(int i = 0; i < TRACE_DEPTH_NUM; i++)
        {
                //BIT_TYPE temp = f.bits[i];
                //printf("%lx\t", temp);
        }
        cout<<endl;
}


bool Simulate::SimInitDFFValue()
{
        srand ( time(NULL) );
        vector<Signal*> vn;
        long total_vn_cnt = 0;
        int n, count_traced; long st;
        
        Value vals[]={Zero,One,Z,X};
        
        //should set the flipflops to 0 first !!!
        for(int j = 0; j < SIM_CYCLE_NUM + 1; j++)
        {
                vector<Signal*> sig;
                vector<Value> val;
                
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        sig.push_back(Ci->getInput(i)->getInput(0));
                }
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
                                val.push_back(vals[rand()%2]);
                                for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
                                        if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
                                                Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
                                                passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
                                        }
                                }
                        }
                        else{
                                val.push_back(Zero);
                        }
                }
                
                setSigValues(sig,val);
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getInput(2)->setVal(One);
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        if(Ci->getSignal(i)->getName()[0]=='R')
                                Ci->getSignal(i)->setVal(One);
                
                sim1cycle();
                
                if( j > 0 )
                {
                        for(int i=0; i<Ci->flipflopSize(); ++i)
                        {
                                if(Ci->getFlipflop(i)->getOutput(0)->getVal() == 1)
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = One;
                                else if(Ci->getFlipflop(i)->getOutput(0)->getVal() == 0)
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = Zero;
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->setOutput();
                
        }
        
        return true;
}


bool Simulate::SimInitDFFValue(string filename)
{
        srand ( time(NULL) );
        vector<Signal*> vn;
        long total_vn_cnt = 0;
        int n, count_traced; long st;
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "init_dff_val";
        ofstream out(str.c_str());
        
        string str1 = filename;
        str1.erase(str1.begin() + str1.find("bench"), str1.end());
        str1 += "gate_weight";
        ofstream kout(str1.c_str());
        
        cout << "DFF map file name is " << str << endl;

        Value vals[]={Zero,One,Z,X};
        
        for(int i=0; i<Ci->gateSize(); ++i){
                Ci->getGate(i)->weight = 0.0;
        }
        
        //should set the flipflops to 0 first !!!
        for(int j = 0; j < SIM_CYCLE_NUM + 1; j++)
        {
                vector<Signal*> sig;
                vector<Value> val;
                
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        sig.push_back(Ci->getInput(i)->getInput(0));
                }
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
                                val.push_back(vals[rand()%2]);
                                for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
                                        if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
                                                Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
                                                passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
                                        }
                                }
                        }
                        else{
                                val.push_back(Zero);
                        }
                }
                
                setSigValues(sig,val);
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getInput(2)->setVal(One);
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        if(Ci->getSignal(i)->getName()[0]=='R')
                                Ci->getSignal(i)->setVal(One);
                
                sim1cycle();
                
                if( j > 0 )
                {
                        //flipflop has weight?
                        for(int i=0; i<Ci->flipflopSize(); ++i)
                        {
                                if(Ci->getFlipflop(i)->getOutput(0)->getVal() == One){
                                        out << "1" << endl;
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = One;
                                        
                                        if(j > 1 && Ci->getFlipflop(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getFlipflop(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getFlipflop(i)->weight += 1.0;
                                }
                                else if(Ci->getFlipflop(i)->getOutput(0)->getVal() == Zero){
                                        out << "0" << endl;
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = Zero;
                                        
                                        if(j > 1 && Ci->getFlipflop(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getFlipflop(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getFlipflop(i)->weight += 1.0;
                                }
                        }
                        
                        for(int i=0; i<Ci->gateSize(); ++i)
                        {
                                if(Ci->getGate(i)->getOutput(0)->getVal() == Zero){
                                        Ci->getGate(i)->getInput(0)->valArray[j-1] = Zero;
                                        
                                        if(j > 1 && Ci->getGate(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getGate(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getGate(i)->weight += 1.0;
                                }
                                else if(Ci->getGate(i)->getOutput(0)->getVal() == One){
                                        Ci->getGate(i)->getInput(0)->valArray[j-1] = One;
                                        
                                        if(j > 1 && Ci->getGate(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getGate(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getGate(i)->weight += 1.0;
                                }
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->setOutput();
                
        }
        
        for(int i=0; i<Ci->gateSize(); ++i)
                kout << Ci->getGate(i)->weight / (double)(SIM_CYCLE_NUM - 1) << endl;
        
        out.close();
        kout.close();
        return true;
}


bool Simulate::SimInitDFFValue_2(string filename)
{
        srand ( time(NULL) );
        vector<Signal*> vn;
        long total_vn_cnt = 0;
        int n, count_traced; long st;
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "init_dff_val";
        ofstream out(str.c_str());
        
        string str1 = filename;
        str1.erase(str1.begin() + str1.find("bench"), str1.end());
        str1 += "gate_weight";
        ofstream kout(str1.c_str());
        
        cout << "DFF map file name is " << str << endl;

        Value vals[]={Zero,One,Z,X};
        
        for(int i=0; i<Ci->gateSize(); ++i){
                Ci->getGate(i)->weight = 0.0;
        }
        
        for(int j = 0; j < SIM_CYCLE_NUM + 1; j++)
        {
                vector<Signal*> sig;
                vector<Value> val;
                
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        sig.push_back(Ci->getInput(i)->getInput(0));
                }
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;
                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
                                val.push_back(vals[rand()%2]);
                                for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
                                        if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
                                                Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
                                                passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
                                        }
                                }
                        }
                        else{
                                val.push_back(Zero);
                        }
                }
                
                setSigValues(sig,val);
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getInput(2)->setVal(One);
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        if(Ci->getSignal(i)->getName()[0]=='R')
                                Ci->getSignal(i)->setVal(One);
                
                sim1cycle();
                
                if( j > 0 )
                {
                        //flipflop has weight?
                        for(int i=0; i<Ci->flipflopSize(); ++i)
                        {
                                if(Ci->getFlipflop(i)->getOutput(0)->getVal() == One){
                                        out << "1" << endl;
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = One;
                                        
                                        if(j > 1 && Ci->getFlipflop(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getFlipflop(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getFlipflop(i)->weight += 1.0;
                                }
                                else if(Ci->getFlipflop(i)->getOutput(0)->getVal() == Zero){
                                        out << "0" << endl;
                                        Ci->getFlipflop(i)->getOutput(0)->valArray[j-1] = Zero;
                                        
                                        if(j > 1 && Ci->getFlipflop(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getFlipflop(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getFlipflop(i)->weight += 1.0;
                                }
                        }
                        
                        for(int i=0; i<Ci->gateSize(); ++i)
                        {
                                if(Ci->getGate(i)->getOutput(0)->getVal() == Zero){
                                        Ci->getGate(i)->getInput(0)->valArray[j-1] = Zero;
                                        
                                        if(j > 1 && Ci->getGate(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getGate(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getGate(i)->weight += 1.0;
                                }
                                else if(Ci->getGate(i)->getOutput(0)->getVal() == One){
                                        Ci->getGate(i)->getInput(0)->valArray[j-1] = One;
                                        
                                        if(j > 1 && Ci->getGate(i)->getOutput(0)->valArray[j-2] 
                                           != Ci->getGate(i)->getOutput(0)->valArray[j-1]) 
                                                Ci->getGate(i)->weight += 1.0;
                                }
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->setOutput();
                
        }
        
        for(int i=0; i<Ci->gateSize(); ++i)
                kout << Ci->getGate(i)->weight / (double)(SIM_CYCLE_NUM - 1) << endl;
        
        out.close();
        kout.close();
        return true;
}


extern int assign_file_id;
bool Simulate::SimInitDFFValue_ITC(string filename)
{
        srand ( time(NULL) );
        vector<Signal*> vn;
        long total_vn_cnt = 0;
        int n, count_traced; long st;
        
        stringstream ss;
        ss << assign_file_id;

        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "init_dff_val_";
        str += ss.str();
        ofstream out(str.c_str());
        cout << "Init DFF file name is " << str << endl;
        
        string str1 = filename;
        str1.erase(str1.begin() + str1.find("bench"), str1.end());
        str1 += "gate_weight_";
        str1 += ss.str();
        ofstream kout(str1.c_str());
        cout << "Gate weight file name is " << str1 << endl;
        
        //init before assign
        initSimulate(filename);
        initMultThread(1);
        
        //parsing the assign file
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "assign_";
        tmp += ss.str();
        cout << "Assign filename is " << tmp << endl;
        
        ifstream in_assign(tmp.c_str());
        if(!in_assign.is_open()){
                cout << "Open assign file failed!" << endl;
                exit(1);
        }
        
        int data, flag; char pin_name[50];
        map<string, int> ctrSigMap;
        const int MAX_LINE_LENGTH  = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        
        while(!in_assign.eof()){
                flag = 0;
                in_assign.getline(line_buffer, MAX_LINE_LENGTH);
                sscanf (line_buffer, "%s\t%d", pin_name, &data);
                tmp = pin_name;
                ctrSigMap[tmp] = data;
                cout << "pin is " << tmp;
                for(int i=0; i<Ci->signalSize(); ++i){
                        if(Ci->getSignal(i)->getName() == tmp){
                                flag = 1;
                                cout << "\tvalue is " << data << endl;
                                Ci->getSignal(i)->untouchible = true;
                                break;
                        }
                }
                
                assert(flag == 1);
        }
        
        //random input pattern generation
        for(int i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->valArray = new Value[SIM_CYCLE_NUM];
                
        for(int i=0; i<Ci->gateSize(); ++i)
                Ci->getGate(i)->weight = 0.0;
        
        myDataType f,g;
        for(int i=0; i<Ci->flipflopSize(); ++i){
                //note that already is "z", just change mul_val1 to 0 at
                //the first cycle is ok
                f.assign((BIT_TYPE)1);
                for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)) - 1; k++)
                        f = f << 1;
                Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[0] = (Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[0] ^ f);
        }

        for(int i=0; i<Ci->inputSize(); ++i){
                if(Ci->getInput(i)->getInput(0)->untouchible == true){
                        if(ctrSigMap[Ci->getInput(i)->getInput(0)->getName()] == 1){
                                f.assign((BIT_TYPE)1);
                                g = f;
                                for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); k++)
                                {
                                        f = f << 1;
                                        f = f | g;
                                }
                                
                                Ci->getInput(i)->getInput(0)->Mult_Val0[0] = f;
                                Ci->getInput(i)->getInput(0)->Mult_Val1[0] = f;
                        }
                        else{
                                Ci->getInput(i)->getInput(0)->Mult_Val0[0].assign((BIT_TYPE)0);
                                Ci->getInput(i)->getInput(0)->Mult_Val1[0].assign((BIT_TYPE)0);
                        }
                }
                else{
                        for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); k++){
                                
                                int val = rand()%2;
                                myDataType temp0, temp1;
                                
                                temp0 = Ci->getInput(i)->getInput(0)->Mult_Val0[0];
                                temp1 = Ci->getInput(i)->getInput(0)->Mult_Val1[0];
                                
                                if(val == 0){
                                        Ci->getInput(i)->getInput(0)->Mult_Val0[0] = (Ci->getInput(i)->getInput(0)->Mult_Val0[0] << 1);
                                        Ci->getInput(i)->getInput(0)->Mult_Val1[0] = (Ci->getInput(i)->getInput(0)->Mult_Val1[0] << 1);
                                }
                                else{
                                        f.assign((BIT_TYPE)1);
                                        Ci->getInput(i)->getInput(0)->Mult_Val0[0] = (Ci->getInput(i)->getInput(0)->Mult_Val0[0] << 1);
                                        Ci->getInput(i)->getInput(0)->Mult_Val0[0] = (Ci->getInput(i)->getInput(0)->Mult_Val0[0] | f);
                                        Ci->getInput(i)->getInput(0)->Mult_Val1[0] = (Ci->getInput(i)->getInput(0)->Mult_Val1[0] << 1);
                                        Ci->getInput(i)->getInput(0)->Mult_Val1[0] = (Ci->getInput(i)->getInput(0)->Mult_Val1[0] | f);
                                }
                        }
                }
        }

        //the actual restoration
        sigList[0].SL.clear();
        for(int i=0; i<Ci->inputSize(); ++i)
                sigList[0].SL.push_back(Ci->getInput(i)->getInput(0));
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                sigList[0].SL.push_back(Ci->getFlipflop(i)->getOutput(0));
        
        while (!sigList[0].SL.empty())
        {
                CurSig[0] = sigList[0].SL.front();
                sigList[0].SL.erase(sigList[0].SL.begin());
                
#ifdef DEBUG_SIMULATE      
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); it!=sigList[0].SL.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        PrintSignalBitVal(CurSig[0], 0);
                        cin.get();
#endif

                if(CurSig[0]->outputSize()!=0){
                        if(CurSig[0]->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<CurSig[0]->outputSize(); ++i){
                                        
                                        if(CurSig[0]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getOutput(i)->setBitOutput(0) == false)
                                                        continue;
                                                
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                //if(!listed && CurSig[0]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                if(!listed)
                                                        sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(0));
                                                
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getOutput(i)->isBitActive(0)){
                                                for(int j=0; j<CurSig[0]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        //if(!listed && CurSig[0]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                        if(!listed)
                                                                sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<CurSig[0]->outputSize(); ++i){
                                        
                                        if(CurSig[0]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getOutput(i)->setBitOutput(0) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                //if(!listed && CurSig[0]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                if(!listed)
                                                        sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getOutput(i)->isBitActive(0)){
                                                for(int j=0; j<CurSig[0]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        //if(!listed && CurSig[0]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                        if(!listed)
                                                                sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
        }
        
        cout << "Finishing simulation..." << endl;
        
        int pre_val, cur_val;
        assert(TRACE_DEPTH_NUM * 8 * sizeof(BIT_TYPE) == SIM_CYCLE_NUM);
        
        const int bit_num = 8 * sizeof(BIT_TYPE);
        for(int k = 0; k < Ci->signalSize(); ++k){
                long count_x = 0;
                long cycle_count = 0;
                Signal* sig = Ci->getSignal(k);
                //cout<<"For signal "<<sig->getName()<<endl;
                
                for(int i = 0; i < TRACE_DEPTH_NUM; i++)
                {
                        for(int j = 0; j < 8 * sizeof(BIT_TYPE); j++)
                        {
                                BIT_TYPE temp1 = sig->Mult_Val0[0].bits[i];
                                BIT_TYPE temp2 = sig->Mult_Val1[0].bits[i];
                                
                                temp1 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                                temp1 >>= bit_num - 1 - j;
                                
                                temp2 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                                temp2 >>= bit_num - 1 - j;
                                
                                if(temp1 == temp2){
                                        cur_val = (int)temp1;
                                        
                                        if(cur_val == 0)
                                                sig->setFlag0(sig->getFlag0()+1);
                                        else
                                                sig->setFlag1(sig->getFlag1()+1);
                                        
                                        if(i !=0 && j!=0){
                                                if(pre_val != cur_val && sig->inputSize())
                                                        sig->getInput(0)->weight++;
                                        }
                                        
                                        //cout<<temp1;
                                }
                                else{
                                        cur_val = 2;
                                        count_x++;
                                        //cout<<"X";
                                }
                                
                                if(sig->inputSize() && sig->getInput(0)->signature() == FLIPFLOP)
                                        sig->valArray[cycle_count++] = (Value)(cur_val);
                                
                                pre_val = cur_val;
                        }
                }
                
                //assert(count_x < 100);
        }
        
        cout << "Start writing to files..." << endl;
        for(int j = 0; j < SIM_CYCLE_NUM; j++){
                for(int k=0; k<Ci->flipflopSize(); ++k){
                        Signal* sig = Ci->getFlipflop(k)->getOutput(0);
                        
                        if(sig->valArray[j] == 0)
                                out << "0" << endl;
                        else if(sig->valArray[j] == 1)
                                out << "1" << endl;
                        else
                                out << "2" << endl;
                }
        }
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                kout << Ci->getFlipflop(i)->weight / (double)(SIM_CYCLE_NUM - 1) << endl;

        for(int i=0; i<Ci->gateSize(); ++i)
                kout << Ci->getGate(i)->weight / (double)(SIM_CYCLE_NUM - 1) << endl;

        for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / SIM_CYCLE_NUM);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / SIM_CYCLE_NUM);
        }
        
        char prob_file[50];
        string pf = filename + ".prob";
        strcpy(prob_file, pf.c_str());
        Ci->write_prob(prob_file, assign_file_id);
        
        cout << "Done!" << endl;

        out.close();
        kout.close();
        return true;
}




bool Simulate::LoadDFFMap(string filename, int ctr_id)//accompanied with siminitDFFvalue
{
        const int MAX_LINE_LENGTH  = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "init_dff_val";
        
        string str1 = filename;
        str1.erase(str1.begin() + str1.find("bench"), str1.end());
        str1 += "gate_weight";
        
        if(ctr_id != -1){
                stringstream ss;
                ss << ctr_id;
                str += "_" + ss.str();
                str1 += "_" + ss.str();
        }
        
        ifstream in(str.c_str());
        if (!in.is_open()) {
                cerr << "Can't open init DFF map file" << endl;
                exit(1);
        }
        
        ifstream kin(str1.c_str());
        if (!kin.is_open()) {
                cerr << "Can't open gate weight file" << endl;
                exit(1);
        }
        
        for(int k=0; k<Ci->gateSize(); ++k)
        {
                kin.getline(line_buffer, MAX_LINE_LENGTH);
                Ci->getGate(k)->weight = atof(line_buffer);
                //cout << " gate " << k << " 's weight is " << Ci->getGate(k)->weight << endl;
        }
        
        int i = 0, j = 0;
        int interval = SIM_CYCLE_NUM;
        
        Value** TEMP_VA = new Value*[Ci->flipflopSize()];
        for(i=0; i<Ci->flipflopSize(); ++i)
        {
                TEMP_VA[i] = new Value[interval];
                for(j = 0; j < interval; j++)
                        TEMP_VA[i][j] = Z;
        }
        
        i = 0; j = 0;
        while(in.getline(line_buffer, MAX_LINE_LENGTH)){
                if(!strcmp(line_buffer,"0")){
                        //cout << "i is " << i << " j is " << j << endl;   
                        TEMP_VA[i++][j] = Zero; 
                }
                else
                        TEMP_VA[i++][j] = One;
                        
                if(i == Ci->flipflopSize())
                {
                        i = 0;
                        j++;
                }
                
                if(j == SIM_CYCLE_NUM)
                        break;
        }
        
        interval = TEST_CASE_NUM * TRACE_DEPTH_NUM * 8 * sizeof(BIT_TYPE);
        //cout << "Actual flipflop range for restoration process is " << interval << endl;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
        {
                //Ci->getFlipflop(i)->getOutput(0)->valArray = new
                //Value[interval];//diable for SA
                for(j = 0; j < interval; j++)
                        Ci->getFlipflop(i)->getOutput(0)->valArray[j] = Z;
        }
        
        for(i = 0 ; i < Ci->flipflopSize(); i++)
        {
                int k = 0;
                while(k < TEST_CASE_NUM){
                        for(j = 0 ; j < TRACE_DEPTH_NUM * 8 * sizeof(BIT_TYPE); j++)
                        {
                                //assert(TEMP_VA[i][j + 317 + 200 * k] != Z);
                                Ci->getFlipflop(i)->getOutput(0)->valArray[j + k * TRACE_DEPTH_NUM * 8 * sizeof(BIT_TYPE)] 
                                        = TEMP_VA[i][j + k * TRACE_DEPTH_NUM * 8 * sizeof(BIT_TYPE)];
                        }
                        
                        k++;
                }        
        }
        
        //for(i = 0 ; i < Ci->flipflopSize(); i++)
        //cout << Ci->getFlipflop(i)->getOutput(0)->valArray[0] << Ci->getFlipflop(i)->getOutput(0)->valArray[1] <<endl;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                delete[] TEMP_VA[i];
        
        delete[] TEMP_VA;
        
        
        char pin_name[50];
        int data;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "assign";
        
        if(ctr_id != -1){
                stringstream ss;
                ss << ctr_id;
                tmp += "_" + ss.str();
        }
        
        //cout << "filename is " << tmp << endl;
        ifstream in_assign(tmp.c_str());
        if(!in_assign.is_open()){
                cout << "Open assign file failed!" << endl;
                exit(1);
        }
        
        //cout << "interval is " << interval << endl;
        interval = SIM_CYCLE_NUM;
        while(!in_assign.eof()){
                in_assign.getline(line_buffer, MAX_LINE_LENGTH);
                sscanf (line_buffer, "%s\t%d", pin_name, &data);
                //s = strtok(line_buffer, "\t\n");
                tmp = pin_name;
                //cout << "pin is " << tmp << endl;
                for(i=0; i<Ci->signalSize(); ++i){
                        if(Ci->getSignal(i)->getName() == tmp){
                                //s = strtok(NULL, " \t\n");
                                //cout << "value is " << data << endl;
                                Ci->getSignal(i)->untouchible = true;
                                Value v = (Value)(data);
                                Ci->getSignal(i)->setVal(v);
                                //temporary comment out
                                //for(j = 0; j < interval; j++)
                                //Ci->getSignal(i)->valArray[j] = v;
                                break;
                        }
                }                
        }
        
        in.close();
        in_assign.close();
        kin.close();
        return true;
}


bool Simulate::LoadInitDFFValue(int offset, int Tid)
{
        myDataType f;
        f.assign((BIT_TYPE)1);
        
        assert(offset < 5);
        int real_offset = offset * TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)) + 137;
        
        assert(offset + TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)) 
               <=  TEST_CASE_NUM * TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));

        //assert(offset <=  SIM_CYCLE_NUM - TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(Tid) == true)
                {
                        for(int j = 0; j < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); j++)
                        {
                                assert(Ci->getFlipflop(i)->getOutput(0)->valArray[j + real_offset] != Z);
                                
                                if(Ci->getFlipflop(i)->getOutput(0)->valArray[j + real_offset] == 1)
                                {
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] 
                                                = ((Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] << 1));
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] =
                                                (Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] | f);
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] 
                                                = ((Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] << 1));
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] =
                                                (Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] | f);
                                }
                                else
                                {
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] 
                                                = (Ci->getFlipflop(i)->getOutput(0)->Mult_Val0[Tid] << 1);
                                        Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] 
                                                = (Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[Tid] << 1);
                                }
                        }
                }
        }
        
        return true;
}

double Simulate::MultCalVN(int Tid)
{
        int mark = 0;
        sigList[Tid].SL.clear();
        
        for(int i=0; i<Ci->inputSize(); ++i)
                if(Ci->getInput(i)->getInput(0)->untouchible == true)
                        sigList[Tid].SL.push_back(Ci->getInput(i)->getInput(0));
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(Tid) == true)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == "g2883")
                                mark = 1;
                        
                        sigList[Tid].SL.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        while (!sigList[Tid].SL.empty())
        {
                CurSig[Tid] = sigList[Tid].SL.front();
                sigList[Tid].SL.erase(sigList[Tid].SL.begin());
                
#ifdef DEBUG_SIMULATE      
                //if(mark == 1)
                {
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); it!=sigList[Tid].SL.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        PrintSignalBitVal(CurSig[Tid], 0);
                        cin.get();
                }
#endif
        
                if(CurSig[Tid]->outputSize()!=0){
                        if(CurSig[Tid]->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<CurSig[Tid]->outputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getOutput(i)->setBitOutput(Tid) == false)
                                                        continue;
                                                
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(0));
                                                
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getOutput(i)->isBitActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<CurSig[Tid]->outputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getOutput(i)->setBitOutput(Tid) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getOutput(i)->isBitActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(CurSig[Tid]->inputSize()!=0){
                        if(CurSig[Tid]->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<CurSig[Tid]->inputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getInput(i)->setBitInput(Tid) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getInput(i)->isBitBackwardActive(Tid)){                                        
                                                for(int j=0; j<CurSig[Tid]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < CurSig[Tid]->inputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getInput(i)->setBitInput(Tid)==false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getInput(i)->isBitBackwardActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }       
        }
        
        pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
        int rc = pthread_mutex_lock(&lock);
        assert(rc == 0);
        BIT_TYPE count = 0;
        for(int i=0; i<Ci->flipflopSize(); ++i)
                count += Ci->getFlipflop(i)->getOutput(0)->isMultKnown(Tid);
        
        //PrintRestoreMap(Tid);
        double temp_VN = (double)count / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        pthread_mutex_unlock(&lock);
        return temp_VN;
}

double Simulate::MultCalVNWOLOCK(int Tid)
{
        int mark = 0;
        sigList[Tid].SL.clear();
        
        for(int i=0; i<Ci->inputSize(); ++i)
                if(Ci->getInput(i)->getInput(0)->untouchible == true)
                {
                        sigList[Tid].SL.push_back(Ci->getInput(i)->getInput(0));
                }

        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(Tid) == true)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == "g2883")
                                mark = 1;
                        
                        sigList[Tid].SL.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        while (!sigList[Tid].SL.empty())
        {
                CurSig[Tid] = sigList[Tid].SL.front();
                sigList[Tid].SL.erase(sigList[Tid].SL.begin());
                
#ifdef DEBUG_SIMULATE      
                //if(mark == 1)
                {
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); it!=sigList[Tid].SL.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        PrintSignalBitVal(CurSig[Tid], 0);
                        cin.get();
                }
#endif
        
                if(CurSig[Tid]->outputSize()!=0){
                        if(CurSig[Tid]->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<CurSig[Tid]->outputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getOutput(i)->setBitOutput(Tid) == false)
                                                        continue;
                                                
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(0));
                                                
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getOutput(i)->isBitActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<CurSig[Tid]->outputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getOutput(i)->setBitOutput(Tid) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getOutput(i)->isBitActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(CurSig[Tid]->inputSize()!=0){
                        if(CurSig[Tid]->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<CurSig[Tid]->inputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getInput(i)->setBitInput(Tid) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getInput(i)->isBitBackwardActive(Tid)){                                        
                                                for(int j=0; j<CurSig[Tid]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < CurSig[Tid]->inputSize(); ++i){
                                        
                                        if(CurSig[Tid]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[Tid]->getInput(i)->setBitInput(Tid)==false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[Tid]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[Tid]->getInput(i)->isBitBackwardActive(Tid)){
                                                for(int j=0; j<CurSig[Tid]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[Tid].SL.begin(); (it!=sigList[Tid].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[Tid]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[Tid]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[Tid].SL.push_back(CurSig[Tid]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }       
        }
        
        BIT_TYPE count = 0;
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                int temp = Ci->getFlipflop(i)->getOutput(0)->isMultKnown(Tid);
                Ci->getFlipflop(i)->getOutput(0)->Cur_P = (double)temp / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                count += temp;
        }
        
        //PrintRestoreMap(Tid);
        double temp_VN = (double)count / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        return temp_VN;
}

pair<double,double> Simulate::reportSRR_GRR(void)
{
        int mark = 0;
        sigList[0].SL.clear();
        
        for(int i=0; i<Ci->inputSize(); ++i)
                if(Ci->getInput(i)->getInput(0)->untouchible == true)
                {
                        sigList[0].SL.push_back(Ci->getInput(i)->getInput(0));
                }

        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(0) == true)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == "g2883")
                                mark = 1;
                        
                        sigList[0].SL.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        while (!sigList[0].SL.empty())
        {
                CurSig[0] = sigList[0].SL.front();
                sigList[0].SL.erase(sigList[0].SL.begin());
                
#ifdef DEBUG_SIMULATE      
                //if(mark == 1)
                {
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); it!=sigList[0].SL.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        PrintSignalBitVal(CurSig[0], 0);
                        cin.get();
                }
#endif
        
                if(CurSig[0]->outputSize()!=0){
                        if(CurSig[0]->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<CurSig[0]->outputSize(); ++i){
                                        
                                        if(CurSig[0]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getOutput(i)->setBitOutput(0) == false)
                                                        continue;
                                                
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[0]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(0));
                                                
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getOutput(i)->isBitActive(0)){
                                                for(int j=0; j<CurSig[0]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[0]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<CurSig[0]->outputSize(); ++i){
                                        
                                        if(CurSig[0]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getOutput(i)->setBitOutput(0) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[0]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getOutput(i)->isBitActive(0)){
                                                for(int j=0; j<CurSig[0]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[0]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(CurSig[0]->inputSize()!=0){
                        if(CurSig[0]->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<CurSig[0]->inputSize(); ++i){
                                        
                                        if(CurSig[0]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getInput(i)->setBitInput(0) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[0]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[0].SL.push_back(CurSig[0]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getInput(i)->isBitBackwardActive(0)){                                        
                                                for(int j=0; j<CurSig[0]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[0]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList[0].SL.push_back(CurSig[0]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < CurSig[0]->inputSize(); ++i){
                                        
                                        if(CurSig[0]->getInput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getInput(i)->setBitInput(0)==false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && CurSig[0]->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList[0].SL.push_back(CurSig[0]->getInput(i)->getInput(1));
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getInput(i)->isBitBackwardActive(0)){
                                                for(int j=0; j<CurSig[0]->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && CurSig[0]->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                                sigList[0].SL.push_back(CurSig[0]->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }       
        }
        
        BIT_TYPE count = 0;
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                int temp = Ci->getFlipflop(i)->getOutput(0)->isMultKnown(0);
                Ci->getFlipflop(i)->getOutput(0)->Cur_P = (double)temp / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                count += temp;
        }
        
        //PrintRestoreMap(Tid);
        double SRR = (double)count / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        
        double w_count = 0.0;
        double tot_weight = 0.0;
        for(int i=0; i<Ci->gateSize(); ++i)
        {
                int temp = Ci->getGate(i)->getOutput(0)->isMultKnown(0);
                w_count += Ci->getGate(i)->weight * temp;
                tot_weight += Ci->getGate(i)->weight;
        }
        
        cout << "total weight is " << tot_weight << endl;
        //PrintRestoreMap(Tid);
        double GRR = w_count / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE))) / tot_weight;//davoodi's idea 
        return make_pair(SRR, GRR);
}


void Simulate::PrintRestoreMap(int Tid){
}


bool lessRStime(Signal* a, Signal* b)
{
        return (a->RStime < b->RStime);
}


bool moreRStime(Signal* a, Signal* b)
{
        return (a->RStime < b->RStime);
}


double Simulate::MultComputVN(int offset){
	
        SimInitDFFValue();
        initMultThread(1);
        LoadInitDFFValue(offset,0);
        return MultCalVNWOLOCK(0);
}


void* work(void *args)
{
        myWorkarg* mwa;// = new myWorkarg;
        mwa = (myWorkarg*) args;
        
        myRetarg* mra = new myRetarg;
        mra->Tid = mwa->Tid;
        mra->VN = mwa->Sim->MultCalVN(mra->Tid);
        //delete mwa;
        return (void*) mra;
}


pair<double, double> Simulate::simSelect(const int trace_size, const char* filename){
        
        Conf* c1;
        Confset* C1;
        clearTraced();
        
        vector<Signal*>::iterator it;
        struct timeval start1, finish1, finish2, finish3;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_greedy";
        
        int i, j = 0;
        
	stringstream ss;
	cout<<"file name is "<<tmp<<endl;        
        ofstream report(tmp.c_str());
        report<<Ci->flipflopSize()<<endl;
        
        const int thread_max = 8;

        initSimulate(tmp);
        //SimInitDFFValue();
        LoadDFFMap(filename, assign_file_id);
        gettimeofday(&start1, NULL);
        
        while(1)
        {
                
                int pos = 0;
                C1 = new Confset();
                
                while(pos < Ci->flipflopSize())
                {
                        int thread_num = (Ci->flipflopSize()-pos >= thread_max)? thread_max : Ci->flipflopSize()-pos;
                        pthread_t PTs[thread_num];
                        
                        initMultithread_GREEDY(thread_num);
                        
                        j = 0;
                        for(i = pos; i < pos + thread_num; ++i)
                        {
                                
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(true, j);
                                c1 = new Conf();
                                c1->tracedSigs.push_back(Ci->getFlipflop(i)->getOutput(0));
                                C1->confs.push_back(c1);
                                
                                j++;
                        }
                        
                        int seed_num = 0;
                        while(seed_num < 3)
                        {
                                if(tracedSigs.size())
                                        initACCMultThread(thread_num, seed_num);
                                else
                                        initMultThread(thread_num);
                                
                                j = 0;
                                for(i = pos; i < pos + thread_num; ++i)
                                {
                                        myWorkarg* mwa= new myWorkarg;
                                        mwa->Tid = j;//should add pos later
                                        mwa->Sim = this;
                                        LoadInitDFFValue(seed_num, j);
                                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                                        
                                        j++;
                                }
                                
                                for(j = 0; j < thread_num; j++)
                                {
                                        myRetarg* mra = new myRetarg;
                                        pthread_join(PTs[j], (void**) &mra);
                                        
                                        C1->confs[mra->Tid + pos]->TV += mra->VN;
                                        C1->confs[mra->Tid + pos]->TVNC += mra->VN;
                                
                                        delete mra;
                                }
                                
                                seed_num++;
                        }
                        
                        pos = i;
                }
                
                sort(C1->confs.begin(), C1->confs.end(), moreTV());
                
                assert(C1->confs.size() > 0);
                assert(C1->confs[0]->tracedSigs.size() == 1);
                
                //generate ref values
                int seed_num = 0;
                while(seed_num < 3){
                        
                        initMultThread(1);
                        LoadInitDFFValue(seed_num,0);
                        MultCalVNWOLOCK(0);
                        
                        for(int i=0; i<Ci->signalSize(); ++i){
                                Ci->getSignal(i)->Mult_Val0_ref[seed_num] = Ci->getSignal(i)->Mult_Val0[0];
                                Ci->getSignal(i)->Mult_Val1_ref[seed_num] = Ci->getSignal(i)->Mult_Val1[0];
                        }
                        
                        seed_num++;
                }
                
                C1->confs[0]->tracedSigs[0]->selected = 1;
                tracedSigs.push_back(C1->confs[0]->tracedSigs[0]);
                
                cout << "selected signal in this round is " << C1->confs[0]->tracedSigs[0]->getName() << endl;
                
                int flag = 0;
                for(i=0; i<Ci->flipflopSize(); ++i)
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == C1->confs[0]->tracedSigs[0]->getName()){
                                cout << "flipflop number is " << i << endl;
                                flag = 1;
                                break;
                        }
                
                assert(flag == 1);

                if(tracedSigs.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                              << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< tracedSigs.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
                        {
                                report<<(*it)->getName()<<"\t";
                                cout<<(*it)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< C1->confs[0]->TV / 3 <<endl;
                        
                        double tmp_SRR = 0.0;
                        double tmp_GRR = 0.0;
                        std::pair<double, double> SRR_GRR;

                        i = 0;
                        while ( i < 3){
                
                                //cout << "Selected signal size is " << tracedSigs.size() << endl;
                
                                for(int j=0; j<Ci->flipflopSize(); ++j)
                                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                                //cout<< "seleted signals' outputs names are...." << endl;
                                for(it = tracedSigs.begin(); it != tracedSigs.end(); it++){
                                        //cout<<(*it)->getName()<<endl;
                                        //report<<(*it)->getName()<<endl;
                                        (*it)->setTraced(true,0);
                                        //tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));// why we need this line?
                                }
                
                                initMultThread(1);
                                LoadInitDFFValue(i, 0);
                                SRR_GRR = reportSRR_GRR();
                                tmp_SRR += SRR_GRR.first;
                                tmp_GRR += SRR_GRR.second;
                
                                i++;
                        }
        
                        cout << "For selecting " << tracedSigs.size() << " of flipflops: " << endl;
                        cout << "SRR is " << tmp_SRR / 3.0<< "\t"; 
                        cout << "GRR is " << tmp_GRR / 3.0 << endl;
                }
                
                if(tracedSigs.size() == 16)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;

                        report<< tracedSigs.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
                        {
                                report<<(*it)->getName()<<"\t";
                                cout<<(*it)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< C1->confs[0]->TV / 3<<endl;
                        
                        double tmp_SRR = 0.0;
                        double tmp_GRR = 0.0;
                        std::pair<double, double> SRR_GRR;

                        i = 0;
                        while (i < 3){
                
                                cout << "Selected signal size is " << tracedSigs.size() << endl;
                
                                for(int j = 0; j < Ci->flipflopSize(); ++j)
                                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                                cout<< "seleted signals' outputs names are...." << endl;
                                for(it = tracedSigs.begin(); it != tracedSigs.end(); it++){
                                        cout<<(*it)->getName()<<endl;
                                        report<<(*it)->getName()<<endl;
                                        (*it)->setTraced(true,0);
                                        //tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));// why we need this line?
                                }
                
                                initMultThread(1);
                                LoadInitDFFValue(i, 0);
                                SRR_GRR = reportSRR_GRR();
                                tmp_SRR += SRR_GRR.first;
                                tmp_GRR += SRR_GRR.second;
                
                                i++;
                        }
        
                        cout << "For selecting " << tracedSigs.size() << " of flipflops: " << endl;
                        cout << "SRR is " << tmp_SRR / 3.0<< "\t"; 
                        cout << "GRR is " << tmp_GRR / 3.0 << endl; 
        
                }
                
                if(tracedSigs.size() == 32)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;

                        report<< tracedSigs.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
                        {
                                report<<(*it)->getName()<<"\t";
                                cout<<(*it)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< C1->confs[0]->TV / 3<<endl;
                        
                        double tmp_SRR = 0.0;
                        double tmp_GRR = 0.0;
                        std::pair<double, double> SRR_GRR;

                        i = 0;
                        while ( i < 3){
                
                                cout << "Selected signal size is " << tracedSigs.size() << endl;
                
                                for(int j=0; j<Ci->flipflopSize(); ++j)
                                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                                cout<< "seleted signals' outputs names are...." << endl;
                                for(it = tracedSigs.begin(); it != tracedSigs.end(); it++){
                                        cout<<(*it)->getName()<<endl;
                                        report<<(*it)->getName()<<endl;
                                        (*it)->setTraced(true,0);
                                        //tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));// why we need this line?
                                }
                
                                initMultThread(1);
                                LoadInitDFFValue(i, 0);
                                SRR_GRR = reportSRR_GRR();
                                tmp_SRR += SRR_GRR.first;
                                tmp_GRR += SRR_GRR.second;
                                
                                i++;
                        }
        
                        cout << "For selecting " << tracedSigs.size() << " of flipflops: " << endl;
                        cout << "SRR is " << tmp_SRR / 3.0<< "\t"; 
                        cout << "GRR is " << tmp_GRR / 3.0 << endl; 
        
                }
                
                cout<< "Trace size is in this round is " << tracedSigs.size() << endl;
                cout<< "Total Visibility is " << C1->confs[0]->TV / 3<< endl;
                
                if(tracedSigs.size() == trace_size)
                        break;
                
                C1->~Confset();               
        }
        
        gettimeofday(&finish3, NULL);
        cout<< "total runtime for Simulation-Based trace selection when selecting "<< trace_size <<" is: "
            << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        report<< "total runtime for Simulation-Based trace selection when selecting "<< trace_size <<" is: "
              << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        report<< tracedSigs.size() << endl;
        report<< "seleted signals are...." << endl;
        
        cout<< "seleted signals are...." << endl;
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
        
        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
        {
                report<<(*it)->getName()<<"\t";
                cout<<(*it)->getName()<<"\t";
        }
        cout<<endl;

        report<<endl;        
        report<<"Final Visibility is "<< C1->confs[0]->TV / 3<<endl;
        
        double tmp_SRR = 0.0;
        double tmp_GRR = 0.0;
        std::pair<double, double> SRR_GRR;

        i = 0;
        while ( i < 3){
                
                cout << "Selected signal size is " << tracedSigs.size() << endl;
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                cout<< "seleted signals' outputs names are...." << endl;
                for(it = tracedSigs.begin(); it != tracedSigs.end(); it++){
                        cout<<(*it)->getName()<<endl;
                        report<<(*it)->getName()<<endl;
                        (*it)->setTraced(true,0);
                        //tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));// why we need this line?
                }
                
                initMultThread(1);
                LoadInitDFFValue(i, 0);
                SRR_GRR = reportSRR_GRR();
                tmp_SRR += SRR_GRR.first;
                tmp_GRR += SRR_GRR.second;
                
                i++;
        }
        
        cout << "For selecting " << tracedSigs.size() << " of flipflops: " << endl;
        cout << "SRR is " << tmp_SRR / 3.0<< "\t"; 
        cout << "GRR is " << tmp_GRR / 3.0 << endl;
        return make_pair(tmp_SRR / 3.0, tmp_GRR / 3.0);
}


struct moreTraceTV : public binary_function<Signal*, Signal *, bool> {
        bool operator()(const Signal *a, const Signal *b){
                return (a->DFF_visibility > b->DFF_visibility);
        }
};


double Simulate::simSelectValeria(const int trace_size, const char* filename){
        
        Conf* c1;
        int i, j;
        Confset* C1;
        clearTraced();
        vector<Signal*>::iterator it;
        //let the whole procedure of trace size 8, 16, 32 finish in one shot
        //assert(trace_size == 8);
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_prune";
        
        ofstream report(tmp.c_str());
        report<<Ci->flipflopSize()<<endl;
        
        const int prune_step = 50;
        const double prune_threshold = 0.93;
        const int thread_max = 24;
        
        initSimulate();
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                addTraced(Ci->getFlipflop(i)->getOutput(0));
        
        //SimInitDFFValue();
        LoadDFFMap(filename, -1);
        
        struct timeval start1, finish1, finish2, finish3;
        gettimeofday(&start1, NULL);

        while(1)
        {
                
                int pos = 0;
                C1 = new Confset();
                
                while(pos < tracedSigs.size())
                {
                        int thread_num = (tracedSigs.size()-pos >= thread_max)? thread_max : tracedSigs.size()-pos;
                        pthread_t PTs[thread_num];
                        
                        initMultithread_PRUNE(thread_num);
                        
                        j = 0;
                        for(i = pos; i < pos + thread_num; ++i)
                        {
                                tracedSigs[i]->setTraced(false, j);
                                
                                c1 = new Conf();
                                c1->tracedSigs.push_back(tracedSigs[i]);
                                C1->confs.push_back(c1);
                                
                                j++;
                        }
                        
                        int seed_num = 0;
                        while(seed_num < 2)
                        {        
                                
                                initMultThread(thread_num);
                                
                                j = 0;
                                for(i = pos; i < pos + thread_num; ++i)
                                {
                                        
                                        myWorkarg* mwa= new myWorkarg;
                                        mwa->Tid = j;//should add pos later
                                        mwa->Sim = this;
                                        LoadInitDFFValue(10 + seed_num * 10,j);
                                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                                        
                                        j++;
                                }
                                
                                for(j = 0; j < thread_num; j++)
                                {
                                        myRetarg* mra = new myRetarg;
                                        pthread_join(PTs[j], (void**) &mra);
                                        
                                        C1->confs[mra->Tid + pos]->TV += mra->VN;
                                        tracedSigs[mra->Tid + pos]->DFF_visibility += mra->VN;
                                        
                                        C1->confs[mra->Tid + pos]->TVNC += mra->VN;
                                        delete mra;
                                }
                                
                                seed_num++;
                        }
                        
                        pos = i;
                }
                
                //cout<<"AfterWards________________________________________________________"<<endl;
                sort(C1->confs.begin(), C1->confs.end(), moreTV());
                
                if(C1->confs[0]->TV > prune_threshold * Ci->flipflopSize() 
                   && tracedSigs.size() > prune_step + 32)
                {
                        sort(tracedSigs.begin(), tracedSigs.end(), moreTraceTV());
                        
                        for(int i = 0; i < prune_step; ++i)
                                tracedSigs[i]->pruned = 1;
                        
                        tracedSigs.erase(tracedSigs.begin(), tracedSigs.begin() + prune_step);
                        continue;
                }
                
                assert(C1->confs.size() > 0);
                assert(C1->confs[0]->tracedSigs.size() == 1);
                
                it = find(tracedSigs.begin(), tracedSigs.end(), C1->confs[0]->tracedSigs[0]);
                assert( it != tracedSigs.end() );
                
                (*it)->pruned = 1;
                tracedSigs.erase(it);

                if(tracedSigs.size() == 32)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                              << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< tracedSigs.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
                        {
                                report<<(*it)->getName()<<"\t";
                                cout<<(*it)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< C1->confs[0]->TV / 2<<endl;
                }
                
                if(tracedSigs.size() == 16)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< tracedSigs.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
                        {
                                report<<(*it)->getName()<<"\t";
                                cout<<(*it)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< C1->confs[0]->TV / 2<<endl;
                }
                
                cout<< "Trace size is in this round is " << tracedSigs.size() << endl;
                cout<< "Total Visibility is " << C1->confs[0]->TV / 2 << endl;
                
                if(tracedSigs.size() == trace_size)
                        break;
                
                C1->~Confset();
                
        }
        
        gettimeofday(&finish3, NULL);
        
        cout<< "total runtime for Simulation-Based trace selection when selecting 8 is: "
            << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        report<< "total runtime for Simulation-Based trace selection when selecting 8 is: "
              << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        report<< tracedSigs.size() << endl;
        report<< "seleted signals are...." << endl;
        
        cout<< "seleted signals are...." << endl;
        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
        {
                report<<(*it)->getName()<<"\t";
                cout<<(*it)->getName()<<"\t";
        }
      
        cout<<endl;
        report<<endl;
        
        printTraced();
        report<<"Final Visibility is "<< C1->confs[0]->TV / 2 <<endl;
        
        return C1->confs[0]->TV / 2;
}


bool Simulate::sim1cycle(void){
	list<Signal*> sigList;
	bool cont=false;
	for(int i=0; i<Ci->flipflopSize(); ++i)
		if(Ci->getFlipflop(i)->getOutput(0)->isKnown())
			sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
        
        int count = 0;
	for(int i=0; i<Ci->inputSize(); ++i)
        {
		if(Ci->getInput(i)->getInput(0)->isKnown())
                {
                        count++;
			sigList.push_back(Ci->getInput(i)->getInput(0));
                }
        }
        
        assert(count == Ci->inputSize());
        
	Signal *s;
        while (!sigList.empty())
        {
                s = sigList.front();
                sigList.erase(sigList.begin());
                
#ifdef DEBUG_SIMULATE
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();
#endif                

                if(s->outputSize()!=0){
                        if(s->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<s->outputSize(); ++i){
                                        
                                        //cout << s->getOutput(i)->signature() << endl;
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP)
                                                continue;
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
				}
			}
			else{
				for(int i=1; i<s->outputSize(); ++i){
                                        
                                        //cout << s->getOutput(i)->signature() << endl;
                                        if(s->getOutput(i)->signature()==FLIPFLOP)
                                                continue;
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
				}
			}
		}
	}
        return cont;
}				
	
bool Simulate::sim1cycleBackward(void){
	list<Signal*> sigList;
	bool cont=false;
	for(int i=0; i<Ci->flipflopSize(); ++i)
		if(Ci->getFlipflop(i)->getInput(1)->isKnown())
			sigList.push_back(Ci->getFlipflop(i)->getInput(1));
	Signal *s;
        while (!sigList.empty())
        {
                s = sigList.back();
                sigList.pop_back();
                
                if(s->untouchible == true)
                        continue;

                if(s->inputSize()!=0){
                        if(s->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP)
                                                continue;
                                        
					if(s->getInput(i)->isBackwardActive()){
						s->getInput(i)->setBackwardVisited(true);
						cont=true;
						
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
					}
				}
			}
			else
				for(int i=1; i<s->inputSize(); ++i){
					
                                        if(s->getInput(i)->signature()==FLIPFLOP)
                                                continue;
                                        
					if(s->getInput(i)->isBackwardActive()){
						s->getInput(i)->setBackwardVisited(true);
						cont=true;
						
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed)
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
					}
				}
                }
	}
        
        return cont;
}				
	
void Simulate::dump(void){
        for(int i=0; i<Ci->signalSize(); ++i)
                cout<<Ci->getSignal(i)->getName()<<" : "<<Ci->getSignal(i)->getVal()<<','<<Ci->getSignal(i)->getP0()<<','<<Ci->getSignal(i)->getP1()<<endl;
}

void Simulate::dumpOutput(void){
        for(int i=0; i<Ci->outputSize(); ++i)
                cout<<Ci->getOutput(i)->getOutput(0)->getName()<<" : "<<Ci->getOutput(i)->getOutput(0)->getVal()<<endl;
}

void Simulate::simNcycle(int n){
	sim1cycle();
	cin.get();
	for(int i=1; i<n; ++i){
		for(int j=0; j<Ci->flipflopSize(); ++j){
			
			Ci->getFlipflop(j)->setOutput();

		}
		sim1cycle();
	}
}

bool Simulate::sim_event_cycle1(void){
	
        bool test = true;
        bool test2 = false;
        while(test){
                test = false;
                for(int i=0; i<passive.size(); ++i){				
                        if(passive[i]->isActive()){
                                test2 = true;
                                passive.erase(passive.begin()+i);
                                --i;
                                test = true;
                        }
                }
        }
        return test2;
}

bool Simulate::sim_event_back_cycle1(void){
	
        bool test = true;
        bool test2 = false;
        while(test){
                test = false;
                for(int i=0; i<passive.size(); ++i){				
                        if(passive[i]->isBackwardActive()){
                                test2 = true;
                                passive.erase(passive.begin()+i);
                                --i;
                                test = true;
                        }
                }
        }
        return test2;
}

void Simulate::sim_event_cycle(void){
	
        bool test = true;
        while(test){
                test = false;
                for(int i=0; i<passive.size(); ++i){
                        if(passive[i]->isActive()){
                                for(int k=0; k<passive[i]->outputSize(); ++k)
                                        for(int k1=0; k1<passive[i]->getOutput(k)->outputSize(); ++k1)
						if(!(passive[i]->getOutput(k)->getOutput(k1)->passive)){
							passive[i]->getOutput(k)->getOutput(k1)->passive = true;
							passive.push_back(passive[i]->getOutput(k)->getOutput(k1));
						}
                                passive[i]->passive = false;
                                passive.erase(passive.begin()+i);
                                --i;
                                test = true;
                        }
                }
        }
}

void Simulate::sim_event(bool fwBw){
	
	passive.clear();
	for(int i=0; i<Ci->gateSize(); ++i)
        {
                if(Ci->getGate(i)->signature() == INPUT)
                        if(Ci->getGate(i)->getInput(0)->untouchible == true)
                                continue;
                
                passive.push_back(Ci->getGate(i));
        }
	bool test = true;
	while(test){
		if(fwBw){
			test = sim_event_cycle1();
			for(int i=0; i<Ci->flipflopSize(); ++i){
				Ci->getFlipflop(i)->setOutput();
			}
		}
		else{
			test = sim_event_back_cycle1();
			for(int i=0; i<Ci->flipflopSize(); ++i){
				Ci->getFlipflop(i)->setInput();
			}
		}
	}
}


bool Simulate::simAllCycle(){

	bool test = false;
	sim1cycle();
	for(int j=0; j<Ci->flipflopSize(); ++j){
		Ci->getFlipflop(j)->setOutput();
	}
	sim1cycle();sim_event(true);
	return test;
}

void Simulate::simNcycleBackward(int n){
	sim1cycleBackward();
	cin.get();
	for(int i=1; i<n; ++i){
		for(int j=0; j<Ci->flipflopSize(); ++j){
			
			Ci->getFlipflop(j)->setInput();
                        
		}
		sim1cycleBackward();
		cin.get();
	}
}

bool Simulate::simAllCycleBackward(){
	for(int j=0; j<Ci->flipflopSize(); ++j){			
                Ci->getFlipflop(j)->setInput();
        }		
	sim1cycleBackward();
	return true;
}

void Simulate::simProb(int n){
        
        int count= 0;
        vector<Value> val;
        vector<Signal*> sig;
        list<Signal*> sigList;
        Value vals[]={Zero,One,Z,X};
        
        forwardSimReg(1);
        for(int i=0; i<Ci->signalSize(); ++i)
                Ci->getSignal(i)->pre_val = Ci->getSignal(i)->getVal();
        
        //this is because we set output after forwardSimReg(1) 
        for(int j=0; j<Ci->flipflopSize(); ++j){			
                if(Ci->getFlipflop(j)->getOutput(0)->getVal() != 0)//initially 0
                        sigList.push_back(Ci->getFlipflop(j)->getOutput(0));
        }
        
        //should set flipflp output to 0 first!!!
        for(int cnt = 0; cnt < n; ++cnt){
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        Ci->getSignal(i)->stored = 0;
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;

                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b')
                        {
                                Value temp_val = vals[rand()%2];
                                if(temp_val != Ci->getInput(i)->getInput(0)->pre_val)
                                {
                                        Ci->getInput(i)->getInput(0)->setVal(temp_val);
                                        Ci->getInput(i)->getInput(0)->pre_val = temp_val;
                                        sigList.push_back(Ci->getInput(i)->getInput(0));
                                }               
                        }
                        else
                                val.push_back(Zero);      
                        
                }
                
                //better check untouchible signal values here
                Signal *s;
                bool cont=false;
                while (!sigList.empty())
                {
                        s = sigList.front();
                        sigList.erase(sigList.begin());
                        
                        //this is the real problem, add these lines are
                        //wrong, let's suppose the same node can be accessed at most twice, should be the case                                                                                                                
                        
                        if(s->stored == 2)
                                continue;
#ifdef DEBUG_SIMULATE
                        
                        cout<<"Current signal values "<<endl;
                        for(int i=0; i<Ci->signalSize(); ++i)
                                cout<<Ci->getSignal(i)->getName()<<" has value "<<Ci->getSignal(i)->getVal()<<endl;

                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();

#endif                
                        s->stored++;
                        if(s->outputSize()!=0){
                                if(s->getOutput(0)->signature() != INPUT){
                                        for(int i=0; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                //should skip then at the
                                                //end of the cycle set flipflop values
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        cont=true;
                                                        
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                if( (!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                    && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                                else{
                                        
                                        for(int i=1; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        
                                                        cont=true;	
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                
                                                                if((!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                   && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
                
                for(int si=0; si<Ci->signalSize(); ++si){
                        
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        else if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                        else
                        {
                                count++;
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i){
                        Ci->getFlipflop(i)->setOutput();
                        if(Ci->getFlipflop(i)->getOutput(0)->getVal() != Ci->getFlipflop(i)->getOutput(0)->pre_val)
                        {
                                Ci->getFlipflop(i)->getOutput(0)->pre_val = Ci->getFlipflop(i)->getOutput(0)->getVal();
                                sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
                        }
                }
                
        }
        
        //cout<<"Number of Unknow signals after simulation is
        //"<<count/MC_NUM<<endl;
        cout<<"Number of Unknow signals after simulation is "<<count/n<<endl;
        
        //this part is for writing the probability file
	for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
	}
        
}

void Simulate::simProb(int n, string filename){
        
        int count= 0;
        vector<Value> val;
        vector<Signal*> sig;
        list<Signal*> sigList;
        Value vals[]={Zero,One,Z,X};
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "init_dff_val";
        ofstream out(str.c_str());
        cout << "DFF map name is " << str << endl;
        
        forwardSimReg(1);
        for(int i=0; i<Ci->signalSize(); ++i)
                Ci->getSignal(i)->pre_val = Ci->getSignal(i)->getVal();
        
        //this is because we set output after forwardSimReg(1) 
        for(int j=0; j<Ci->flipflopSize(); ++j){			
                if(Ci->getFlipflop(j)->getOutput(0)->getVal() != 0)//initially 0
                        sigList.push_back(Ci->getFlipflop(j)->getOutput(0));
        }
        
        for(int cnt = 0; cnt < n; ++cnt){
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        Ci->getSignal(i)->stored = 0;
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;

                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b')
                        {
                                Value temp_val = vals[rand()%2];
                                if(temp_val != Ci->getInput(i)->getInput(0)->pre_val)
                                {
                                        Ci->getInput(i)->getInput(0)->setVal(temp_val);
                                        Ci->getInput(i)->getInput(0)->pre_val = temp_val;
                                        sigList.push_back(Ci->getInput(i)->getInput(0));
                                }               
                        }
                        else{
                                val.push_back(Zero);      
                        }
                }
                
                //better check untouchible signal values here
                Signal *s;
                bool cont=false;
                while (!sigList.empty())
                {
                        s = sigList.front();
                        sigList.erase(sigList.begin());
                        
                        //this is the real problem, add these lines are
                        //wrong, let's suppose the same node can be accessed at most twice, should be the case                                                                                                                
                        
                        if(s->stored == 2)
                                continue;
#ifdef DEBUG_SIMULATE
                        
                        cout<<"Current signal values "<<endl;
                        for(int i=0; i<Ci->signalSize(); ++i)
                                cout<<Ci->getSignal(i)->getName()<<" has value "<<Ci->getSignal(i)->getVal()<<endl;

                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();

#endif                
                        s->stored++;
                        if(s->outputSize()!=0){
                                if(s->getOutput(0)->signature() != INPUT){
                                        for(int i=0; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                //should skip then at the
                                                //end of the cycle set flipflop values
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        cont=true;
                                                        
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                if( (!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                    && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                                else{
                                        
                                        for(int i=1; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        
                                                        cont=true;	
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                
                                                                if((!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                   && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
                
                for(int si=0; si<Ci->signalSize(); ++si){
                        
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        else if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                        else
                        {
                                count++;
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i){
                        Ci->getFlipflop(i)->setOutput();
                        //this may happen at the beginning of the simulation
                        //assert(Ci->getFlipflop(i)->getOutput(0)->getVal()
                        //!= 2);
                        if(cnt < SIM_CYCLE_NUM)
                                out << Ci->getFlipflop(i)->getOutput(0)->getVal() << endl;
                        
                        if(Ci->getFlipflop(i)->getOutput(0)->getVal() != Ci->getFlipflop(i)->getOutput(0)->pre_val)
                        {
                                Ci->getFlipflop(i)->getOutput(0)->pre_val = Ci->getFlipflop(i)->getOutput(0)->getVal();
                                sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
                        }
                }
                
        }
        
        //cout<<"Number of Unknow signals after simulation is "<<count/MC_NUM<<endl;
        cout<<"Number of Unknow signals after simulation is "<<count/n<<endl;

        //this part is for writing the probability file
	for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
	}
        
        out.close();
}

void Simulate::simProb_2(int n, string filename){
        
        int count= 0;
        vector<Value> val;
        vector<Signal*> sig;
        list<Signal*> sigList;
        Value vals[]={Zero,One,Z,X};
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "init_dff_val";
        ofstream out(str.c_str());
        cout << "DFF map name is " << str << endl;
        
        string str2 = filename;
        str2.erase(str2.begin() + str2.find("bench"), str2.end());
        str2 += "assign";
        
        forwardSimReg(1, str2);
        
        for(int i=0; i<Ci->signalSize(); ++i)
                Ci->getSignal(i)->pre_val = Ci->getSignal(i)->getVal();
        
        //this is because we set output after forwardSimReg(1) 
        for(int j=0; j<Ci->flipflopSize(); ++j){			
                if(Ci->getFlipflop(j)->getOutput(0)->getVal() != 0)//initially 0
                        sigList.push_back(Ci->getFlipflop(j)->getOutput(0));
        }
        
        for(int cnt = 0; cnt < n; ++cnt){
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        Ci->getSignal(i)->stored = 0;
                
                val.clear();
                for(int i=0; i<Ci->inputSize(); ++i){
                        
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                continue;

                        if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b')
                        {
                                Value temp_val = vals[rand()%2];
                                if(temp_val != Ci->getInput(i)->getInput(0)->pre_val)
                                {
                                        Ci->getInput(i)->getInput(0)->setVal(temp_val);
                                        Ci->getInput(i)->getInput(0)->pre_val = temp_val;
                                        sigList.push_back(Ci->getInput(i)->getInput(0));
                                }               
                        }
                        else{
                                val.push_back(Zero);      
                        }
                }
                
                //better check untouchible signal values here
                Signal *s;
                bool cont=false;
                while (!sigList.empty())
                {
                        s = sigList.front();
                        sigList.erase(sigList.begin());
                        
                        //this is the real problem, add these lines are
                        //wrong, let's suppose the same node can be accessed at most twice, should be the case                                                                                                                
                        
                        if(s->stored == 2)
                                continue;
#ifdef DEBUG_SIMULATE
                        
                        cout<<"Current signal values "<<endl;
                        for(int i=0; i<Ci->signalSize(); ++i)
                                cout<<Ci->getSignal(i)->getName()<<" has value "<<Ci->getSignal(i)->getVal()<<endl;

                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();

#endif                
                        s->stored++;
                        if(s->outputSize()!=0){
                                if(s->getOutput(0)->signature() != INPUT){
                                        for(int i=0; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                //should skip then at the
                                                //end of the cycle set flipflop values
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        cont=true;
                                                        
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                if( (!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                    && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                                else{
                                        
                                        for(int i=1; i<s->outputSize(); ++i){
                                                
                                                //cout << s->getOutput(i)->signature() << endl;
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                                
                                                if(s->getOutput(i)->isActive()){
                                                        
                                                        cont=true;	
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                
                                                                if((!listed) && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' 
                                                                   && s->getOutput(i)->getOutput(j)->getVal() != s->getOutput(i)->getOutput(j)->pre_val)
                                                                {
                                                                        s->getOutput(i)->getOutput(j)->pre_val = s->getOutput(i)->getOutput(j)->getVal();
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
                
                for(int si=0; si<Ci->signalSize(); ++si){
                        
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        else if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                        else
                        {
                                count++;
                        }
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i){
                        Ci->getFlipflop(i)->setOutput();
                        //this may happen at the beginning of the simulation
                        //assert(Ci->getFlipflop(i)->getOutput(0)->getVal()
                        //!= 2);
                        if(cnt < SIM_CYCLE_NUM)
                                out << Ci->getFlipflop(i)->getOutput(0)->getVal() << endl;
                        
                        if(Ci->getFlipflop(i)->getOutput(0)->getVal() != Ci->getFlipflop(i)->getOutput(0)->pre_val)
                        {
                                Ci->getFlipflop(i)->getOutput(0)->pre_val = Ci->getFlipflop(i)->getOutput(0)->getVal();
                                sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
                        }
                }
                
        }
        
        //cout<<"Number of Unknow signals after simulation is "<<count/MC_NUM<<endl;
        cout<<"Number of Unknow signals after simulation is "<<count/n<<endl;

        //this part is for writing the probability file
	for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
	}
        
        out.close();
}

extern vector<int> sim_vals;
void Simulate::forwardSim_event(int n){
	
        Value vals[]={Zero,One,Z,X};
        list<Signal*> sigList;
	vector<Signal*> sig;
	vector<Value> val;
        int count= 0;
        
	for(int i=0; i<Ci->inputSize(); ++i){
		sig.push_back(Ci->getInput(i)->getInput(0));
	}
        
        for(int j=0; j<Ci->flipflopSize(); ++j){
                if(Ci->getFlipflop(j)->getOutput(0)->isKnown() == false)
                        Ci->getFlipflop(j)->getOutput(0)->setVal(Zero);
        }
        
        for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->stored = 0;
                Ci->getSignal(i)->setFlag0(0);
                Ci->getSignal(i)->setFlag1(0);
        }
        
        //before go into the loop, let's first deal with the situation when
        //after simulate 1 cycle, there are still unknow signals
        for(int cnt=0; cnt < n; ++cnt){
                
                for(int i=0; i<Ci->signalSize(); ++i)
                        Ci->getSignal(i)->stored = 0;
                
		val.clear();
		for(int i=0; i<Ci->inputSize(); ++i){
			if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b'){
				val.push_back(vals[rand()%2]);
				for(int k=0; k<Ci->getInput(i)->getInput(0)->outputSize(); ++k){
					if(!(Ci->getInput(i)->getInput(0)->getOutput(k)->passive)){
						Ci->getInput(i)->getInput(0)->getOutput(k)->passive = true;
						passive.push_back(Ci->getInput(i)->getInput(0)->getOutput(k));
					}
				}
			}
			else{
				val.push_back(Zero);
			}
		}
                
		setSigValues(sig,val);
                bool cont=false;
                
                for(int i=0; i<Ci->inputSize(); ++i)
                        if(Ci->getInput(i)->getInput(0)->untouchible == true)
                                Ci->getInput(i)->getInput(0)->setVal(One);
                
                //this part is for input
                for(int i = 0; i < sig.size(); i++)
                {
                        if( sim_vals[sig[i]->getIndex()] != val[i] && sig[i]->getName()[0] != 'b' && sig[i]->getName()[0] != 'n')
                        {
                                sim_vals[sig[i]->getIndex()] = val[i];
                                sigList.push_back(sig[i]);
                        }
                }
                
                Signal *s;
                while (!sigList.empty())
                {
                        s = sigList.front();
                        sigList.erase(sigList.begin());
                        
                        //this is the real problem, add these lines are
                        //wrong, let's suppose the same node can be
                        //accessed at most twice, should be the case
                        if(s->stored == 2)
                                continue;
#ifdef DEBUG_SIMULATE
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();
#endif                
                        s->stored++;
                        if(s->outputSize()!=0){
                                if(s->getOutput(0)->signature()!=INPUT){
                                        for(int i=0; i<s->outputSize(); ++i){
                                                
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                       
                                                if(s->getOutput(i)->isActive()){
                                                        cont=true;
                                                        
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                if(s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                        }
                                                }
                                        }
                                }
                                else{
                                
                                        for(int i=1; i<s->outputSize(); ++i){
						
                                                if(s->getOutput(i)->signature()==FLIPFLOP)
                                                        continue;
                                       
                                                if(s->getOutput(i)->isActive()){
                                                
                                                        cont=true;	
                                                        for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                                
                                                                bool listed = false;
                                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                        if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                                listed = true;
                                                                }
                                                                
                                                                if(s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                        sigList.push_back(s->getOutput(i)->getOutput(j));
                                                        }
                                                }
                                        }
                                }
                        }
                }
                
                for(int si=0; si<Ci->signalSize(); ++si){
                        
                        if(Ci->getSignal(si)->getVal()==Zero)
                                Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
                        else if(Ci->getSignal(si)->getVal()==One)
                                Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
                        else
                        {
                                count++;
                        }
                }
        
                //collecting information for hybrid gates
                int k,bit;
                for(int i = 0; i < Ci->hgateSize(); ++i){
                
                        //collecting backtracing events
                        for(int j = 0; j < Ci->getHGate(i)->inputSize(); j++)
                        {
                                bit = 0;
                                for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                {
                                        if(k == j)
                                                continue;
                                        else
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+0][bit] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal()
                                                   && ((HybridNode*)Ci->getHGate(i))->events[2*j+0][bit] != 2)
                                                        break;
                                                else
                                                        bit++;
                                }                        
                
                                if(k == Ci->getHGate(i)->inputSize())
                                {
                                        for(k = 0; k < Ci->getHGate(i)->outputSize(); k++)
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+0][Ci->getHGate(i)->inputSize()-1+k] 
                                                   != Ci->getSignal(Ci->getHGate(i)->getOutput(k)->getIndex())->getVal() && 
                                                   ((HybridNode*)Ci->getHGate(i))->events[2*j+0][Ci->getHGate(i)->inputSize()-1+k] != 2)
                                                        break;
                                }
                                else
                                        continue;
                        
                                if(k == Ci->getHGate(i)->outputSize())
                                {
                                        ((HybridNode*)Ci->getHGate(i))->BR_event[2*j+0]++;
                                        continue;
                                }
                        }
                
                        for(int j = 0; j < Ci->getHGate(i)->inputSize(); j++)
                        {
                                bit = 0;
                                for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                {
                                        if(k == j)
                                                continue;
                                        else
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+1][bit] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal()
                                                   && ((HybridNode*)Ci->getHGate(i))->events[2*j+1][bit] != 2)
                                                        break;
                                                else
                                                        bit++;
                                }
                        
                                if(k == Ci->getHGate(i)->inputSize())
                                {
                                        for(k = 0; k < Ci->getHGate(i)->outputSize(); k++)
                                                if(((HybridNode*)Ci->getHGate(i))->events[2*j+1][Ci->getHGate(i)->inputSize()-1+k] 
                                                   != Ci->getSignal(Ci->getHGate(i)->getOutput(k)->getIndex())->getVal()
                                                   && ((HybridNode*)Ci->getHGate(i))->events[2*j+1][Ci->getHGate(i)->inputSize()-1+k] != 2)
                                                        break;
                                }
                                else
                                        continue;
                        
                                if(k == Ci->getHGate(i)->outputSize())
                                {
                                        ((HybridNode*)Ci->getHGate(i))->BR_event[2*j+1]++;
                                        continue;
                                }
                        }

                        //collecting forward resotre information
                        int cnt,flag;
                        vector<int*>::iterator it;
                        for(int j = 0; j < Ci->getHGate(i)->outputSize(); j++)
                        {
                                flag = 0;
                                cnt = 0;
                                for(it = ((HybridNode*)Ci->getHGate(i))->OFR0.begin(); it != ((HybridNode*)Ci->getHGate(i))->OFR0.end(); it++)
                                {
                                        for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                                if((*it)[k] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal() 
                                                   && (*it)[k] != 2)
                                                        break;
                                
                                        if(k == Ci->getHGate(i)->inputSize())
                                        {
                                                flag = 1;
                                                break;
                                        }
                                        cnt++;
                                }
                        
                                if(flag == 1)
                                {
                                        ((HybridNode*)Ci->getHGate(i))->FR0_event[cnt]++;
                                        continue;
                                }
                        
                                flag = 0;
                                cnt = 0;
                                for(it = ((HybridNode*)Ci->getHGate(i))->OFR1.begin(); it != ((HybridNode*)Ci->getHGate(i))->OFR1.end(); it++)
                                {
                                        for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                                if((*it)[k] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal() 
                                                   && (*it)[k] != 2)
                                                        break;
                                
                                        if(k == Ci->getHGate(i)->inputSize())
                                        {
                                                flag = 1;
                                                break;
                                        }
                                        cnt++;
                                }
                        
                                if(flag == 1)
                                {
                                        ((HybridNode*)Ci->getHGate(i))->FR1_event[cnt]++;
                                        continue;
                                }
                        }
                        
                        cnt = 0;
                        //collecting extra events
                        for(it = ((HybridNode*)Ci->getHGate(i))->extra_events.begin(); it != ((HybridNode*)Ci->getHGate(i))->extra_events.end(); it++)
                        {
                                flag = 0;
                                for(k = 0; k < Ci->getHGate(i)->inputSize(); k++)
                                {
                                        if((*it)[0] == k)
                                                continue;
                                        else
                                        {
                                                if((*it)[k+2] != Ci->getSignal(Ci->getHGate(i)->getInput(k)->getIndex())->getVal() 
                                                   && (*it)[k+2] != 2)
                                                        break;
                                        }
                                }
                        
                                if(k != Ci->getHGate(i)->inputSize())
                                        continue;
                        
                                for(k = Ci->getHGate(i)->inputSize()-1; k < Ci->getHGate(i)->inputSize()-1+Ci->getHGate(i)->outputSize(); k++)
                                {
                                        if((*it)[k+2] != Ci->getSignal(Ci->getHGate(i)->getOutput(k-Ci->getHGate(i)->inputSize()+1)->getIndex())->getVal() 
                                           && (*it)[k+2] != 2)
                                                break;
                                }
                        
                                if(k != Ci->getHGate(i)->inputSize()-1+Ci->getHGate(i)->outputSize())
                                        continue;
                                else
                                        ((HybridNode*)Ci->getHGate(i))->Extra_br_event[cnt]++;
                                
                                cnt++;
                        }
                 }
                
                for(int i=0; i<Ci->flipflopSize(); ++i){
                        Ci->getFlipflop(i)->setOutput();
                }
        }
        
        //cout<<"Number of Unknow signals after simulation is "<<count/MC_NUM<<endl;
        cout<<"Number of Unknow signals after simulation is "<<count/n<<endl;

        //this part is for writing the probability file
	for(int i=0; i<Ci->signalSize(); ++i){
        Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / n);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / n);
	}
}

extern double criteria;
void Simulate::forwardSimReg(int n){
	Value vals[]={Zero,One,Z,X};
	initSimulate();
        
        for(int gi=0; gi<Ci->gateSize(); ++gi){
                
                if(Ci->getGate(gi)->getName() == "NAND2") 
                        ((Nand2Node*)Ci->getGate(gi))->initEventStat();
                if(Ci->getGate(gi)->getName() == "NOR2")
                        ((Nor2Node*)Ci->getGate(gi))->initEventStat();
                
                Ci->getGate(gi)->correlated = 0;
                Ci->getGate(gi)->initCorStat();
        }
        
	vector<Signal*> sig;
	vector<Value> val;

	for(int i=0; i<Ci->inputSize(); ++i){
		if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b' && Ci->getInput(i)->getInput(0)->untouchible == false){
			sig.push_back(Ci->getInput(i)->getInput(0));
			val.push_back(vals[rand()%2]);
		}
		else{
                        if(Ci->getInput(i)->getInput(0)->untouchible == false)
                        {
                                sig.push_back(Ci->getInput(i)->getInput(0));
                                val.push_back(One);
                        }
		}
	}	
        
	setSigValues(sig,val);
	sim1cycle();
        
	for(int i=0; i<Ci->flipflopSize(); ++i){
                Ci->getFlipflop(i)->setOutput();
        }
	
	for(int cnt=0; cnt<(n-1); ++cnt){
		sig.clear();
		val.clear();
                //if for this part we check the signals that have values
                //different from the previous cycle, we can use an
                //event-driven simulator for much faster simulation of
                //signal probabilities. 
		for(int i=0; i<Ci->inputSize(); ++i){
			if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b' && Ci->getInput(i)->getInput(0)->untouchible == false){
				sig.push_back(Ci->getInput(i)->getInput(0));
				val.push_back(vals[rand()%2]);
			}
			else{
				sig.push_back(Ci->getInput(i)->getInput(0));
				val.push_back(Zero);
			}
		}
                
		setSigValues(sig,val);
		simAllCycle();	

		for(int si=0; si<Ci->signalSize(); ++si){
                        if(Ci->getSignal(si)->getVal()==Zero)
				Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
			if(Ci->getSignal(si)->getVal()==One)
				Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
		}
                
                int j,entry,ret_val;
                //go through all gates, no three-input gates
                for(int gi=0; gi<Ci->gateSize(); ++gi){
                        if(Ci->getGate(gi)->inputSize() == 2)//two inputs
                        {
                                entry=0;
                                for(j = 0; j < 2; j++)
                                {
                                        if(Ci->getGate(gi)->getInput(j)->getVal() == One)
                                                ret_val = 1;
                                        else if(Ci->getGate(gi)->getInput(j)->getVal() == Zero)
                                                ret_val = 0;
                                        else
                                                ret_val = -1;
                                        
                                        if(ret_val != -1)
                                                entry += ret_val * pow(2,j);
                                }
                                
                                if(Ci->getGate(gi)->getName() == "NAND2")
                                {
                                        if(Ci->getGate(gi)->getInput(0)->getVal() == One 
                                           && Ci->getGate(gi)->getInput(1)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_fr0_c++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == One 
                                                && Ci->getGate(gi)->getInput(0)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_br0[0]++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == One 
                                                && Ci->getGate(gi)->getInput(1)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_br0[1]++;
                                        else
                                        {
                                                
                                        }
                                }
                                
                                if(Ci->getGate(gi)->getName() == "NOR2")
                                {
                                        if(Ci->getGate(gi)->getInput(0)->getVal() == Zero 
                                           && Ci->getGate(gi)->getInput(1)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_fr1_c++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == Zero 
                                                && Ci->getGate(gi)->getInput(0)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_br1[0]++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == Zero 
                                                && Ci->getGate(gi)->getInput(1)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_br1[1]++;
                                        else
                                        {
                                                
                                        }
                                }

                                Ci->getGate(gi)->updateCorStat(entry);
                        }
                        else if(Ci->getGate(gi)->inputSize() == 3)//three inputs
                        {
                                entry=0;
                                for(j = 0; j < 3; j++)
                                {
                                        if(Ci->getGate(gi)->getInput(j)->getVal() == One)
                                                ret_val = 1;
                                        else if(Ci->getGate(gi)->getInput(j)->getVal() == Zero)
                                                ret_val = 0;
                                        else
                                                ret_val = -1;
                                        
                                        if(ret_val != -1)
                                                entry += ret_val * pow(2,j);
                                }
                                
                                Ci->getGate(gi)->updateCorStat(entry);
                        }
                        else
                        {
                                //do nothing
                        }
                }
	}//n cycles after
        
        int c1=0,c2=0,c3=0;
        int cnt_two_in=0,cnt_three_in=0;
        int impossible=0;
        
        for(int gi=0; gi<Ci->gateSize(); ++gi){
#ifdef DEBUG_SIMULATE
                if(Ci->getGate(gi)->getName() == "NAND2")
                {
                        cout<<"Index is "<<Ci->getGate(gi)->index<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_fr0_c<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_br0[0]<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_br0[1]<<endl;
                }

                if(Ci->getGate(gi)->getName() == "NOR2")
                {
                        cout<<"Index is "<<Ci->getGate(gi)->index<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_fr1_c<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_br1[0]<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_br1[1]<<endl;
                }
#endif
                if(Ci->getGate(gi)->inputSize() == 2)//two inputs
                {
                        c2++;                          
                        
                        if((double)Ci->getGate(gi)->findMajority()/(double)n >= criteria)
                        {
                                cnt_two_in++;
                                Ci->getGate(gi)->correlated++;
                                if(Ci->getGate(gi)->getInput(0)->inputSize() > 1 
                                   || Ci->getGate(gi)->getInput(1)->inputSize() > 1)
                                        impossible++;
                        }
                }
                else if(Ci->getGate(gi)->inputSize() == 3)
                {
                        c3++;
                        
                        if((double)Ci->getGate(gi)->findMajority()/(double)n >= criteria/2)
                        {
                                cnt_three_in++;
                                Ci->getGate(gi)->correlated++;
                        }
                }
                else
                        c1++;
        }
        
        cout<<"total number of gates is "<<Ci->gateSize()<<endl;
        cout<<"# of one-input gates is "<<c1<<endl;
        cout<<"# of two-inputs gates is "<<c2<<endl;

        cout<<"# of three-inputs gates is "<<c3<<endl;
        cout<<"# of correlated two-inputs gates is "<<cnt_two_in<<endl;
        cout<<"# of impossible two-inputs gates is "<<impossible<<endl;
        cout<<"# of correlated three-inputs gates is "<<cnt_three_in<<endl;
        
	return;
}

void Simulate::forwardSimReg(int n, string filename){
	Value vals[]={Zero,One,Z,X};
	initSimulate(filename);
        
        for(int gi=0; gi<Ci->gateSize(); ++gi){
                
                if(Ci->getGate(gi)->getName() == "NAND2") 
                        ((Nand2Node*)Ci->getGate(gi))->initEventStat();
                if(Ci->getGate(gi)->getName() == "NOR2")
                        ((Nor2Node*)Ci->getGate(gi))->initEventStat();
                
                Ci->getGate(gi)->correlated = 0;
                Ci->getGate(gi)->initCorStat();
        }
        
	vector<Signal*> sig;
	vector<Value> val;

	for(int i=0; i<Ci->inputSize(); ++i){
		if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b' && Ci->getInput(i)->getInput(0)->untouchible == false){
			sig.push_back(Ci->getInput(i)->getInput(0));
			val.push_back(vals[rand()%2]);
		}
		else{
                        if(Ci->getInput(i)->getInput(0)->untouchible == false)
                        {
                                sig.push_back(Ci->getInput(i)->getInput(0));
                                val.push_back(vals[rand()%2]);//Min
                                //val.push_back(One);
                        }
		}
	}	
        
	setSigValues(sig,val);
	sim1cycle();
        
	for(int i=0; i<Ci->flipflopSize(); ++i){
                Ci->getFlipflop(i)->setOutput();
        }
	
	for(int cnt=0; cnt<(n-1); ++cnt){
		sig.clear();
		val.clear();
                //if for this part we check the signals that have values
                //different from the previous cycle, we can use an
                //event-driven simulator for much faster simulation of
                //signal probabilities. 
		for(int i=0; i<Ci->inputSize(); ++i){
			if(Ci->getInput(i)->getInput(0)->getName()[0] != 'b' && Ci->getInput(i)->getInput(0)->untouchible == false){
				sig.push_back(Ci->getInput(i)->getInput(0));
				val.push_back(vals[rand()%2]);
			}
                        else if(Ci->getInput(i)->getInput(0)->getName()[0] == 'b' && Ci->getInput(i)->getInput(0)->untouchible == true){
                                sig.push_back(Ci->getInput(i)->getInput(0));
                        }
			else{
				sig.push_back(Ci->getInput(i)->getInput(0));
                                val.push_back(vals[rand()%2]);//Min
				//val.push_back(Zero);
			}
		}
                
		setSigValues(sig,val);
		simAllCycle();	

		for(int si=0; si<Ci->signalSize(); ++si){
                        if(Ci->getSignal(si)->getVal()==Zero)
				Ci->getSignal(si)->setFlag0(Ci->getSignal(si)->getFlag0()+1);
			if(Ci->getSignal(si)->getVal()==One)
				Ci->getSignal(si)->setFlag1(Ci->getSignal(si)->getFlag1()+1);
		}
                
                int j,entry,ret_val;
                //go through all gates, no three-input gates
                for(int gi=0; gi<Ci->gateSize(); ++gi){
                        if(Ci->getGate(gi)->inputSize() == 2)//two inputs
                        {
                                entry=0;
                                for(j = 0; j < 2; j++)
                                {
                                        if(Ci->getGate(gi)->getInput(j)->getVal() == One)
                                                ret_val = 1;
                                        else if(Ci->getGate(gi)->getInput(j)->getVal() == Zero)
                                                ret_val = 0;
                                        else
                                                ret_val = -1;
                                        
                                        if(ret_val != -1)
                                                entry += ret_val * pow(2,j);
                                }
                                
                                if(Ci->getGate(gi)->getName() == "NAND2")
                                {
                                        if(Ci->getGate(gi)->getInput(0)->getVal() == One 
                                           && Ci->getGate(gi)->getInput(1)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_fr0_c++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == One 
                                                && Ci->getGate(gi)->getInput(0)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_br0[0]++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == One 
                                                && Ci->getGate(gi)->getInput(1)->getVal() == One)
                                                ((Nand2Node*)Ci->getGate(gi))->event_br0[1]++;
                                        else
                                        {
                                                
                                        }
                                }
                                
                                if(Ci->getGate(gi)->getName() == "NOR2")
                                {
                                        if(Ci->getGate(gi)->getInput(0)->getVal() == Zero 
                                           && Ci->getGate(gi)->getInput(1)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_fr1_c++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == Zero 
                                                && Ci->getGate(gi)->getInput(0)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_br1[0]++;
                                        else if(Ci->getGate(gi)->getOutput(0)->getVal() == Zero 
                                                && Ci->getGate(gi)->getInput(1)->getVal() == Zero)
                                                ((Nor2Node*)Ci->getGate(gi))->event_br1[1]++;
                                        else
                                        {
                                                
                                        }
                                }

                                Ci->getGate(gi)->updateCorStat(entry);
                        }
                        else if(Ci->getGate(gi)->inputSize() == 3)//three inputs
                        {
                                entry=0;
                                for(j = 0; j < 3; j++)
                                {
                                        if(Ci->getGate(gi)->getInput(j)->getVal() == One)
                                                ret_val = 1;
                                        else if(Ci->getGate(gi)->getInput(j)->getVal() == Zero)
                                                ret_val = 0;
                                        else
                                                ret_val = -1;
                                        
                                        if(ret_val != -1)
                                                entry += ret_val * pow(2,j);
                                }
                                
                                Ci->getGate(gi)->updateCorStat(entry);
                        }
                        else
                        {
                                //do nothing
                        }
                }
	}//n cycles after
        
        int c1=0,c2=0,c3=0;
        int cnt_two_in=0,cnt_three_in=0;
        int impossible=0;
        
        for(int gi=0; gi<Ci->gateSize(); ++gi){
#ifdef DEBUG_SIMULATE
                if(Ci->getGate(gi)->getName() == "NAND2")
                {
                        cout<<"Index is "<<Ci->getGate(gi)->index<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_fr0_c<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_br0[0]<<endl;
                        cout<<((Nand2Node*)Ci->getGate(gi))->event_br0[1]<<endl;
                }

                if(Ci->getGate(gi)->getName() == "NOR2")
                {
                        cout<<"Index is "<<Ci->getGate(gi)->index<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_fr1_c<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_br1[0]<<endl;
                        cout<<((Nor2Node*)Ci->getGate(gi))->event_br1[1]<<endl;
                }
#endif
                if(Ci->getGate(gi)->inputSize() == 2)//two inputs
                {
                        c2++;                          
                        
                        if((double)Ci->getGate(gi)->findMajority()/(double)n >= criteria)
                        {
                                cnt_two_in++;
                                Ci->getGate(gi)->correlated++;
                                if(Ci->getGate(gi)->getInput(0)->inputSize() > 1 
                                   || Ci->getGate(gi)->getInput(1)->inputSize() > 1)
                                        impossible++;
                        }
                }
                else if(Ci->getGate(gi)->inputSize() == 3)
                {
                        c3++;
                        
                        if((double)Ci->getGate(gi)->findMajority()/(double)n >= criteria/2)
                        {
                                cnt_three_in++;
                                Ci->getGate(gi)->correlated++;
                        }
                }
                else
                        c1++;
        }
        
        cout<<"total number of gates is "<<Ci->gateSize()<<endl;
        cout<<"# of one-input gates is "<<c1<<endl;
        cout<<"# of two-inputs gates is "<<c2<<endl;

        cout<<"# of three-inputs gates is "<<c3<<endl;
        cout<<"# of correlated two-inputs gates is "<<cnt_two_in<<endl;
        cout<<"# of impossible two-inputs gates is "<<impossible<<endl;
        cout<<"# of correlated three-inputs gates is "<<cnt_three_in<<endl;
        
	return;
}

bool Simulate::PreSimHybrid1Trace()
{
        list<Signal*> sigList;
	bool cont=false;
        string DFF_Under_Sim;
        
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                if(Ci->getSignal(i)->untouchible == true)
                {/*
                        for(int j = 0; j < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); j++)
                                assert(Ci->getSignal(i)->valArray[j] != Z);
                        
                        if(Ci->getSignal(i)->valArray[0] == One)
                                Ci->getSignal(i)->setVal(One);
                        else
                                Ci->getSignal(i)->setVal(Zero);
                 */     
                        sigList.push_back(Ci->getSignal(i));
                }
        }
        
        //cout<< "gigi's size is " << sigList.size() <<endl;
        
        Signal *s;
	while (!sigList.empty())
        {
                s = sigList.front();
                sigList.erase(sigList.begin());
                                
                if(s->stored == 1)
                        continue;
#ifdef DEBUG_SIMULATE
                cout<<"Current signals in list are"<<endl;
                for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                        cout<<(*it)->getName()<<"\t";
                cout<<endl;
                
                cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                cin.get();
#endif
                s->stored = 1;
                
                if(s->outputSize()!=0){
                        if(s->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP){
                                                s->getOutput(i)->setOutput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                                
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;
                                                
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP){
                                                s->getOutput(i)->setOutput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getOutput(i)->getOutput(0));
                                                continue;
                                        }

                                        if(s->getOutput(i)->isActive()){
                                                
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(s->inputSize()!=0){
                        if(s->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP){
                                                s->getInput(i)->setInput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getInput(i)->getInput(1));
                                                continue;
                                        }

                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP){
                                                s->getInput(i)->setInput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getInput(i)->getInput(1));
                                                continue;
                                        }

                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                        
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                           sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }
        }
        
        return cont;
}

bool Simulate::simHybrid1Trace(bool test)
{
        int Cmark = 0;
        list<Signal*> sigList;
	bool cont=false;
        string DFF_Under_Sim;
        for(int i=0; i<Ci->signalSize(); ++i)
        {
                if(Ci->getSignal(i)->untouchible == true)
                {
                        /*
                        for(int j = 0; j < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); j++)
                                assert(Ci->getSignal(i)->valArray[j] != Z);
                        if(Ci->getSignal(i)->valArray[0] == 1)
                                Ci->getSignal(i)->setVal(One);
                        else
                                Ci->getSignal(i)->setVal(Zero);
                        */
                        sigList.push_back(Ci->getSignal(i));
                }
        }

        for(int i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced())
                {
                        DFF_Under_Sim = Ci->getFlipflop(i)->getOutput(0)->getName();
                        if(test == true){
                                Ci->getFlipflop(i)->getOutput(0)->setVal(One);
                        }
                        else{
                                Ci->getFlipflop(i)->getOutput(0)->setVal(Zero);
                        }
                        Ci->getFlipflop(i)->setInput();
                        sigList.push_back(Ci->getFlipflop(i)->getInput(1));
			sigList.push_back(Ci->getFlipflop(i)->getOutput(0));
                }
        
        Signal *s;
	while (!sigList.empty())
        {
                s = sigList.front();
                sigList.erase(sigList.begin());
                
                if(s->stored == 1)
                        continue;

#ifdef DEBUG_SIMULATE
                if(Cmark == 1)
                {
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList.begin(); it!=sigList.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        cout<<"signal under simulation "<< s->getName() << " value " << s->getVal()<< endl;
                        cin.get();
                }
#endif                
                s->stored = 1;
                
                if(s->outputSize()!=0){
                        if(s->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP){
                                                s->getOutput(i)->setOutput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                                
                                        
                                        if(s->getOutput(i)->isActive()){
                                                cont=true;
                                                
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                                
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<s->outputSize(); ++i){
                                        
                                        if(s->getOutput(i)->signature()==FLIPFLOP){
                                                s->getOutput(i)->setOutput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getOutput(i)->getOutput(0));
                                                continue;
                                        }

                                        if(s->getOutput(i)->isActive()){
                                                
                                                cont=true;	
                                                for(int j=0; j<s->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                                sigList.push_back(s->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
                if(s->inputSize()!=0){
                        if(s->getInput(0)->signature()!=OUTPUT){
                                for(int i=0; i<s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP){
                                                s->getInput(i)->setInput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getInput(i)->getInput(1));
                                                continue;
                                        }

                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b')
                                                                sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                        else
                        {
                                for(int i = 1; i < s->inputSize(); ++i){
                                        
                                        if(s->getInput(i)->signature()==FLIPFLOP){
                                                s->getInput(i)->setInput();
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                        if((*it)->getName()== s->getInput(i)->getInput(1)->getName())
                                                                listed = true;
                                                }
                                                if(!listed && s->getInput(i)->getInput(1)->getName().c_str()[0] != 'b') 
                                                        sigList.push_back(s->getInput(i)->getInput(1));
                                                continue;
                                        }

                                        if(s->getInput(i)->isBackwardActive()){
                                                
                                                s->getInput(i)->setBackwardVisited(true);
                                                cont=true;
                                                        
                                                for(int j=0; j<s->getInput(i)->inputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList.begin(); (it!=sigList.end()) && (!listed); ++it){
                                                                if((*it)->getName()== s->getInput(i)->getInput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        if(!listed && s->getInput(i)->getInput(j)->getName().c_str()[0] != 'b') 
                                                           sigList.push_back(s->getInput(i)->getInput(j));
                                                }
                                        }
                                }
                        }
                }
        }
        
        return cont;
}

double probAdjust(Signal* s, double Pbar)
{
        return ((1 - s->Cur_P > Pbar)? Pbar : 1 - s->Cur_P);
}

double probAdjust_mm(int idx, Signal* s, double Pbar)
{
        return ((1 - s->RR_array[idx] > Pbar)? Pbar : 1 - s->Cur_P);
}

double probAdjustGate(Node* n, Signal* s, double Pbar)
{
        return ((1.0 - s->Cur_P > Pbar)? Pbar : 1.0 - s->Cur_P);
}

double probAdjustGate_mm(int idx, Node* n, Signal* s, double Pbar)
{
        return ((1.0 - s->RR_array[idx] > Pbar)? Pbar : 1.0 - s->Cur_P);
}

double probAdjustBack(Signal* s, double Pbar)
{
        if(s->Cur_P > 1.0)
                return 0.0;
        else
                return ((s->Cur_P > Pbar)? Pbar : s->Cur_P);
}

double Simulate::huerSelect2ProcessFor1(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;

        while(i != trace_size)
        {
                weight = 0.0;
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight = (*it_map)->R0.size() * (*it_map)->P0 + 
                                (*it_map)->R1.size() * (*it_map)->P1;
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                }
                
                if(weight == 0.0)
                        break;
              
                //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;

                i++;
                selected_traces.push_back((*it_map1)->DFF_id);
                for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                {
                        if(it_map != it_map1)
                        {
                                for(it_set = (*it_map1)->R0.begin(); it_set != (*it_map1)->R0.end(); it_set++)
                                {
                                        it_set1 = (*it_map)->R0.find(*it_set);
                                        if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= (*it_map1)->P0)
                                                (*it_map)->R0.erase(it_set1);
                                        
                                        it_set1 = (*it_map)->R1.find(*it_set);
                                        if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= (*it_map1)->P0)
                                                (*it_map)->R1.erase(it_set1);
                              
                                }
                                
                                for(it_set = (*it_map1)->R1.begin(); it_set != (*it_map1)->R1.end(); it_set++)
                                {
                                        it_set1 = (*it_map)->R1.find(*it_set);
                                        if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= (*it_map1)->P1)
                                                (*it_map)->R1.erase(it_set1);
                                
                                        it_set1 = (*it_map)->R0.find(*it_set);
                                        if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= (*it_map1)->P1)
                                                (*it_map)->R0.erase(it_set1);
                                }
                        }
                }

                Mymap.erase(it_map1);
        }
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

bool moreVNSAMPLE(sample s1, sample s2)
{
        return(s1.VN > s2.VN);
}

bool rateMapSort(mapRate a1, mapRate a2)
{
        return (a1.weight > a2.weight);
}

bool TrateMapSort(TmapRate a1, TmapRate a2)
{
        return (a1.weight > a2.weight);
}

double Simulate::huerSelect2ProcessFor2(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces, const char* filename){
        
        int i, j;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<mapRate> MR;
        assert(selected_traces.size() == 0);
        
        cout<<"file name is "<<filename<<endl;        
        ofstream report(filename);
        report<<Ci->flipflopSize()<<endl;
        
        struct timeval start1, finish1, finish2, finish3;
        gettimeofday(&start1, NULL);
        
        while(selected_traces.size() < trace_size)
        {
                MR.clear();
                weight = 0.0;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                temp_weight += probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P0);
                        
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                temp_weight += probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                        
                        mapRate myMR;
                        myMR.weight = temp_weight;
                        myMR.it_map = it_map;                
                        MR.push_back(myMR);
                }
                
                if(weight == 0.0)
                        break;
              
                std::sort(MR.begin(), MR.end(), rateMapSort);
                
                double largest_weight = MR[0].weight;
                const double topK = 0.05;
                for(j = 0; j < MR.size(); j++)
                {
                        if(MR[j].weight < topK * largest_weight)
                                break;
                        
                        MR[j].weight = 0.0;
                }
                
                assert(j != 0);
                
                if(selected_traces.size() == 0)
                        j = 100;
                
                if( selected_traces.size() > 0 && j > 50 )
                        j = 50;
                
                if(j > MR.size())
                        j = MR.size();
                else
                        MR.resize(j);
                
                cout << "j is " << j << endl;
                const int thread_num = j;
                pthread_t PTs[thread_num];
                
                for(j = 0; j < thread_num; j++)
                {
                        for(i=0; i < Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                        for(i=0; i < selected_traces.size(); ++i)
                                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                        Ci->getFlipflop((*(MR[j].it_map))->DFF_id)->getOutput(0)->setTraced(true,j);
                }
                
                int seed_num = 0;
                while(seed_num < 2)
                {       
                        
                        initMultThread(thread_num);
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;
                                mwa->Sim = this;
                                LoadInitDFFValue(10 + seed_num * 10, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                                
                                //cout<<"Tid is "<<mra->Tid + pos<<endl;
                                MR[mra->Tid].weight += mra->VN;
                                delete mra;
                        }
                        
                        seed_num++;
                }
                
                for(j = 0; j < thread_num; j++)
                        cout << (*(MR[j].it_map))->DFF_id << " 's restorability is " << MR[j].weight << endl; 

                //cin.get();
                
                cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;
                std::sort(MR.begin(), MR.end(), rateMapSort);
                
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop((*(MR[0].it_map))->DFF_id)->getOutput(0)->getName() << endl;
                
                cout<<"VN is "<<MR[0].weight / 2 <<endl;
                selected_traces.push_back((*(MR[0].it_map))->DFF_id);
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                
                initMultThread(1);
                LoadInitDFFValue(0,0);
                double cur_VN = MultCalVNWOLOCK(0);
                
                double restime = 0.0;
                for(int j=0; j<Ci->flipflopSize(); ++j)
                {
                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                        Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                it_map1 = MR[0].it_map;
                Mymap.erase(it_map1);
                
                if(selected_traces.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                              << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                if(selected_traces.size() == 16)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, cur_VN);
                
                if(selected_traces.size() == 32)
                {
                        gettimeofday(&finish3, NULL);

                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                }        
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

double Simulate::huerSelect2ProcessFor2Com(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces, const char* filename){
        
        int i, j;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;

        vector<mapRate> MR;
        assert(selected_traces.size() == 0);
        
        cout<<"file name is "<<filename<<endl;        
        ofstream report(filename);
        report<<Ci->flipflopSize()<<endl;
        
        clock_t start1, finish1, finish2, finish3;
        start1 = clock();
        
        while(selected_traces.size() < trace_size)
        {
                weight = 0.0;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                temp_weight += probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P0);
                        
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                temp_weight += probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }        
                }
                
                if(weight == 0.0)
                        break;
              
                selected_traces.push_back((*it_map1)->DFF_id);
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                
                initMultThread(1);
                LoadInitDFFValue(0,0);
                double cur_VN = MultCalVNWOLOCK(0);
                
                double restime = 0.0;
                for(int j=0; j<Ci->flipflopSize(); ++j)
                {
                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                        Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                //The current commented area is for the case when there is
                //no simulation help for restoration demand adjustment
                Mymap.erase(it_map1);
                
                if(selected_traces.size() == 8)
                {
                        finish1 = clock();

                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( (finish1 - start1) / CLOCKS_PER_SEC ) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                              << ( (finish1 - start1) / CLOCKS_PER_SEC ) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        //addIslands(selected_traces, cur_VN);
                }
                
                if(selected_traces.size() == 16)
                {
                        finish2 = clock();
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( (finish2 - start1) / CLOCKS_PER_SEC ) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( (finish2 - start1) / CLOCKS_PER_SEC ) << endl;

                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        //addIslands(selected_traces, cur_VN);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, cur_VN);
                
                if(selected_traces.size() == 32)
                {
                        finish3 = clock();
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( (finish2 - start1) / CLOCKS_PER_SEC ) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( (finish2 - start1) / CLOCKS_PER_SEC ) << endl;

                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                }        
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}


double probAdjust2(Signal* s, const double Pbar, const int val)
{
        assert(val != 2);
        if(val == 1)
                return ((1 - s->Cur_P1 > Pbar)? Pbar : 1 - s->Cur_P1);
        else
                return ((1 - s->Cur_P0 > Pbar)? Pbar : 1 - s->Cur_P0);
}

double probAdjustBack2(Signal* s, const double Pbar, const int val)
{
        assert(val != 2);
        if(val == 1)
        {
                if(s->Cur_P1 > 1.0)
                        return 0.0;
                else
                        return ((s->Cur_P1 > Pbar)? Pbar : s->Cur_P1);
        }
        else
        {
                if(s->Cur_P0 > 1.0)
                        return 0.0;
                else
                        return ((s->Cur_P0 > Pbar)? Pbar : s->Cur_P0);
        }
}

double Simulate::huerSelect2ProcessFor2Mod(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0, j;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        vector<resVal>::iterator it_set;
        vector<resVal>::iterator it_set1;
        vector<int>::iterator it_vec;

        vector<mapRate> MR;
        while(i != trace_size)
        {
                weight = 0.0;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0_P.begin(); it_set != (*it_map)->R0_P.end(); it_set++)
                                temp_weight += probAdjust2(Ci->getFlipflop((*it_set).DFF_id)->getOutput(0), 
                                                           (*it_map)->P0, (*it_set).val);
                        
                        for(it_set = (*it_map)->R1_P.begin(); it_set != (*it_map)->R1_P.end(); it_set++)
                                temp_weight += probAdjust2(Ci->getFlipflop((*it_set).DFF_id)->getOutput(0), 
                                                           (*it_map)->P1, (*it_set).val);
                        
                        mapRate myMR;
                        myMR.weight = temp_weight;
                        myMR.it_map = it_map;
                }
                
                if(weight == 0.0)
                        break;
                
                std::sort(MR.begin(), MR.end(), rateMapSort);
                
                double largest_weight = MR[0].weight;
                const double topK = 0.1;
                for(j = 0; j < MR.size(); j++)
                {
                        if(MR[j].weight < topK * largest_weight)
                                break;
                        
                        MR[j].weight = 0.0;
                }
                
                assert(j != 0);
                MR.resize(j);

                const int thread_num = j;
                pthread_t PTs[thread_num];
                
                for(j = 0; j < thread_num; j++)
                {
                        for(i=0; i<Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                        for(i=0; i<Ci->flipflopSize(); ++i)
                        {
                                if(Ci->getFlipflop(i)->getOutput(0)->chosen == true)       
                                {
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true,j);
                                }
                        }
                }
                
                int seed_num = 0;
                while(seed_num < 3)
                {       
                        
                        initMultThread(thread_num);
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;
                                mwa->Sim = this;
                                LoadInitDFFValue(50 + seed_num * 150, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                                MR[mra->Tid].weight += mra->VN;
                                delete mra;
                        }
                                
                        seed_num++;
                }
                
                std::sort(MR.begin(), MR.end(), rateMapSort);
                i++;
                
                it_map1 = MR[j].it_map;
                for(it_set = (*it_map1)->R0_P.begin(); it_set != (*it_map1)->R0_P.end(); it_set++)
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 += (*it_map1)->P0;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 += (*it_map1)->P0;
                
                for(it_set = (*it_map1)->R1_P.begin(); it_set != (*it_map1)->R1_P.end(); it_set++)
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 += (*it_map1)->P1;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 += (*it_map1)->P1;
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                {
                        if(Ci->getFlipflop(j)->getOutput(0)->Cur_P0 > 1.0)
                                Ci->getFlipflop(j)->getOutput(0)->Cur_P0 = 1.0;
                        if(Ci->getFlipflop(j)->getOutput(0)->Cur_P1 > 1.0)
                                Ci->getFlipflop(j)->getOutput(0)->Cur_P1 = 1.0;
                }
                
                Mymap.erase(it_map1);
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

double Simulate::huerSelect2ProcessBack(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                assert(Ci->getFlipflop(j)->getOutput(0)->Cur_P == 0.0);
        //calculating the summation of all
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
        {
                for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                        Ci->getFlipflop(*it_set)->getOutput(0)->Cur_P += (*it_map)->P0;
                
                for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                        Ci->getFlipflop(*it_set)->getOutput(0)->Cur_P += (*it_map)->P1;
        }
        
        //assert(islands.size() != 0);
        int prune_start_num = Ci->flipflopSize() - islands.size();
        while(prune_start_num - i != trace_size)
        {
                weight = 1.0e20;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                temp_weight += probAdjustBack(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P0);
                        
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                temp_weight += probAdjustBack(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                        
                        if(temp_weight < weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                }
                
                if(weight == 1.0e20)
                        break;
              
                //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;

                i++;
                selected_traces.push_back((*it_map1)->DFF_id);
                for(it_set = (*it_map1)->R0.begin(); it_set != (*it_map1)->R0.end(); it_set++)
                        Ci->getFlipflop(*it_set)->getOutput(0)->Cur_P -= (*it_map1)->P0;
                
                for(it_set = (*it_map1)->R1.begin(); it_set != (*it_map1)->R1.end(); it_set++)
                        Ci->getFlipflop(*it_set)->getOutput(0)->Cur_P -= (*it_map1)->P1;
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        if(Ci->getFlipflop(j)->getOutput(0)->Cur_P < 0.0)
                                Ci->getFlipflop(j)->getOutput(0)->Cur_P = 0.0;
                
                Mymap.erase(it_map1);
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(true,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(false,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        for(i = 0; i < islands.size(); i++)
                Ci->getFlipflop(islands[i])->getOutput(0)->setTraced(false,0);

        cout<<"selected DFFs are"<<endl;
        selected_traces.clear();
        for(int j=0; j < Ci->flipflopSize(); ++j)
                if(Ci->getFlipflop(j)->getOutput(0)->getTraced(0) == true)
                {
                        cout<<Ci->getFlipflop(j)->getOutput(0)->getName()<<"\t";
                        selected_traces.push_back(j);
                }
        cout<<endl;

        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

double Simulate::huerSelect2ProcessBackMod(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        vector<resVal>::iterator it_set;
        vector<resVal>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
        {
                assert(Ci->getFlipflop(j)->getOutput(0)->Cur_P0 == 0.0);
                assert(Ci->getFlipflop(j)->getOutput(0)->Cur_P1 == 0.0);
        }
                
        //calculating the summation of all
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
        {
                for(it_set = (*it_map)->R0_P.begin(); it_set != (*it_map)->R0_P.end(); it_set++)
                {
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 += (*it_map)->P0;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 += (*it_map)->P0;
                }
                
                for(it_set = (*it_map)->R1_P.begin(); it_set != (*it_map)->R1_P.end(); it_set++)
                {
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 += (*it_map)->P1;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 += (*it_map)->P1;
                }
                
        }
        
        //assert(islands.size() != 0);
        int prune_start_num = Ci->flipflopSize() - islands.size();
        while(prune_start_num - i != trace_size)
        {
                weight = 1.0e20;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        
                        for(it_set = (*it_map)->R0_P.begin(); it_set != (*it_map)->R0_P.end(); it_set++)
                                temp_weight += probAdjustBack2(Ci->getFlipflop((*it_set).DFF_id)->getOutput(0), (*it_map)->P0, (*it_set).val);
                        
                        for(it_set = (*it_map)->R1_P.begin(); it_set != (*it_map)->R1_P.end(); it_set++)
                                temp_weight += probAdjustBack2(Ci->getFlipflop((*it_set).DFF_id)->getOutput(0), (*it_map)->P1, (*it_set).val);
                        
                        if(temp_weight < weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                }
                
                if(weight == 1.0e20)
                        break;
              
                //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;

                i++;
                selected_traces.push_back((*it_map1)->DFF_id);
                for(it_set = (*it_map1)->R0_P.begin(); it_set != (*it_map1)->R0_P.end(); it_set++)
                {
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 -= (*it_map1)->P0;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 -= (*it_map1)->P0;
                }
                
                for(it_set = (*it_map1)->R1_P.begin(); it_set != (*it_map1)->R1_P.end(); it_set++)
                {
                        if((*it_set).val == 1)
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P1 -= (*it_map1)->P1;
                        else
                                Ci->getFlipflop((*it_set).DFF_id)->getOutput(0)->Cur_P0 -= (*it_map1)->P1;
                }
                
                for(int j=0; j<Ci->flipflopSize(); ++j)
                        if(Ci->getFlipflop(j)->getOutput(0)->Cur_P < 0.0)
                                Ci->getFlipflop(j)->getOutput(0)->Cur_P = 0.0;
                
                Mymap.erase(it_map1);
        }
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(true,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(false,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        for(i = 0; i < islands.size(); i++)
                Ci->getFlipflop(islands[i])->getOutput(0)->setTraced(false,0);

        cout<<"selected DFFs are"<<endl;
        selected_traces.clear();
        for(int j=0; j < Ci->flipflopSize(); ++j)
                if(Ci->getFlipflop(j)->getOutput(0)->getTraced(0) == true)
                {
                        cout<<Ci->getFlipflop(j)->getOutput(0)->getName()<<"\t";
                        selected_traces.push_back(j);
                }
        cout<<endl;

        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

double Simulate::huerSelect3Process(const int trace_size, vector<resMap*> &Mymap , vector<int> &selected_traces){
        
        int i = 0;
        double weight, temp_weight;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        map<int,double>::iterator it_RM;
        map<int,double>::iterator it_RM1;
        vector<int>::iterator it_vec;

        while(i != trace_size)
        {
                weight = 0.0;
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight = (*it_map)->R.size();
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                }
                
                if(weight == 0.0)
                        break;
              
                i++;
                selected_traces.push_back((*it_map1)->DFF_id);
                for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                {
                        if(it_map != it_map1)
                        {
                                for(it_RM = (*it_map1)->R.begin(); it_RM != (*it_map1)->R.end(); it_RM++)
                                {
                                        it_RM1 = (*it_map)->R.find((*it_RM).first);
                                        if(it_RM1 != (*it_map)->R.end())//&& (*it_RM1).second <= (*it_RM).second)
                                                (*it_map)->R.erase(it_RM1);
                                }
                        }
                }

                Mymap.erase(it_map1);
        }
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        return MultCalVNWOLOCK(0);
}

bool moreFanouts(Signal* a, Signal* b)
{
        return (a->outputs.size() > b->outputs.size());
}

void Simulate::PickTop3MostFanout(){
        
        vector<Signal*> sigList;
        for(int i=0; i<Ci->signalSize(); ++i)
                sigList.push_back(Ci->getSignal(i));
        
        std::sort(sigList.begin(),sigList.end(),moreFanouts);
        
        for(int i = 0; i < 8; i++)
                cout<<sigList[i]->getName()<<"\t";
        cout<<endl;
}

void Simulate::SetProb(){
        
        int count0, count1;
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                count0 = 0; count1 = 0;
                for(int j = 0; j < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); j++)
                {
                        assert(Ci->getFlipflop(i)->getOutput(0)->valArray[j] != 2);
                        if(Ci->getFlipflop(i)->getOutput(0)->valArray[j] == 1)
                                count1++;
                        else
                                count0++;
                }
                
                Ci->getFlipflop(i)->getOutput(0)->setP0((double)count0 / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE))) );
                Ci->getFlipflop(i)->getOutput(0)->setP1((double)count1 / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE))) );
        }
        
}

void Simulate::updateRStime(){
}

void Simulate::updateRSmapWeight(vector<resMap*> &Mymap)
{
        double temp_total;
        map<int,double>::iterator it_RM;
        vector<resMap*>::iterator it_map;
        for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
        {
                (*it_map)->weight = 0.0;
                temp_total = 0.0;
                for(it_RM = (*it_map)->R.begin(); it_RM != (*it_map)->R.end(); it_RM++)
                {
                        if(Ci->getSignal((*it_RM).first)->RStime == 0)
                                temp_total += 1;
                        else
                                temp_total += (double)1/Ci->getSignal((*it_RM).first)->RStime;
                }
                
                //(*it_map)->weight += temp_total;
                (*it_map)->weight += temp_total;
                //(*it_map)->weight += (*it_map)->P1 * temp_total;
        }
}

bool moreSecondWeight(Signal* a, Signal* b)
{
        return (a->weight > b->weight);
}

bool moreRSWeight(resMap* a, resMap* b)
{
        return (a->weight > b->weight);
}

bool Simulate::DFS_Forward(Node* ni, const int DFF_id, vector<Node*>& PassedNodes)
{
        for(int i = 0; i < ni->outputSize(); i++)
        {
                for(int j = 0; j < ni->getOutput(i)->outputSize(); j++)
                {
                        
                        if(ni->getOutput(i)->getOutput(j)->visited == true)
                                continue;
                        
                        if(ni->getOutput(i)->getOutput(j)->signature() == FLIPFLOP)
                        {
                                if(std::find(Ci->getFlipflop(DFF_id)->nearbyDFFs.begin(), 
                                             Ci->getFlipflop(DFF_id)->nearbyDFFs.end(), 
                                             ((FlipflopNode*)ni->getOutput(i)->getOutput(j))->FF_index) == Ci->getFlipflop(DFF_id)->nearbyDFFs.end())
                                        Ci->getFlipflop(DFF_id)->nearbyDFFs.push_back(((FlipflopNode*)ni->getOutput(i)->getOutput(j))->FF_index);
                        }
                        else
                        {
                                ni->getOutput(i)->getOutput(j)->visited = true;
                                PassedNodes.push_back(ni->getOutput(i)->getOutput(j));
                                DFS_Forward(ni->getOutput(i)->getOutput(j), DFF_id, PassedNodes);
                        }
                }        
        }

        return true;
}

bool Simulate::DFS_Backward(Node* ni, const int DFF_id, vector<Node*>& PassedNodes)
{
        for(int i = 0; i < ni->inputSize(); i++)
        {
                for(int j = 0; j < ni->getInput(i)->inputSize(); j++)
                {
                        if(ni->getInput(i)->getInput(j)->signature() == FLIPFLOP)
                        {
                                if(std::find(Ci->getFlipflop(DFF_id)->nearbyDFFs.begin(), 
                                             Ci->getFlipflop(DFF_id)->nearbyDFFs.end(), 
                                             ((FlipflopNode*)ni->getInput(i)->getInput(j))->FF_index) == Ci->getFlipflop(DFF_id)->nearbyDFFs.end())
                                        Ci->getFlipflop(DFF_id)->nearbyDFFs.push_back(((FlipflopNode*)ni->getInput(i)->getInput(j))->FF_index);
                        }
                        else
                        {
                                ni->getInput(i)->getInput(j)->visited = true;
                                PassedNodes.push_back(ni->getInput(i)->getInput(j));
                                DFS_Forward(ni->getInput(i)->getInput(j), DFF_id, PassedNodes);
                        }
                }
        }

        return true;
}

void Simulate::DFFSearchNearby(){
        
        vector<Node*> PassedNodes;
        for(int i=0; i<Ci->flipflopSize(); ++i)
        {
                PassedNodes.clear();
                DFS_Forward(Ci->getFlipflop(i), i, PassedNodes);
                DFS_Backward(Ci->getFlipflop(i), i, PassedNodes);
                
                for(int j = 0; j < PassedNodes.size(); j++)
                        PassedNodes[j]->visited = false;
                
                Ci->getFlipflop(i)->visited = true;
                assert(Ci->getFlipflop(i)->nearbyDFFs.size() != 0);
        }
        
}

void Simulate::Sample_Procedure(const int sample_times){
        
        srand ( time(NULL) );
        const int thread_max = 24;
        vector<sample> mySamples;
        
        int i, j, pos = 0;
        while(pos < sample_times)
        {
                int thread_num = (sample_times-pos >= thread_max)? thread_max : (sample_times-pos);
                pthread_t PTs[thread_num];
                
                for(j = 0; j < thread_num; j++)
                {
                        sample MS;
                        for(i=0; i<Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                        for(i=0; i<Ci->flipflopSize(); ++i)
                        {
                                if(Ci->getFlipflop(i)->getOutput(0)->chosen == true)       
                                {
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true,j);
                                        MS.DFF_ids.push_back(i);
                                        
                                        int try_time = 0;
                                        while(try_time < 20)
                                        {
                                                int num = rand()%Ci->getFlipflop(i)->nearbyDFFs.size();
                                                if(Ci->getFlipflop(num)->getOutput(0)->getTraced(j) == false)
                                                {
                                                        MS.DFF_ids.push_back(num);
                                                        Ci->getFlipflop(num)->getOutput(0)->setTraced(true,j);
                                                        break;
                                                }
                                                
                                                try_time++;
                                        }
                                }
                        }
                        
                        MS.VN = 0.0;
                        mySamples.push_back(MS);
                }
                
                int seed_num = 0;
                while(seed_num < 3)
                {       
                        
                        initMultThread(thread_num);
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;//should add pos later
                                mwa->Sim = this;
                                LoadInitDFFValue(50 + seed_num * 150, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                        
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                                
                                //cout<<"Tid is "<<mra->Tid + pos<<endl;
                                mySamples[mra->Tid + pos].VN += mra->VN;                                
                                delete mra;
                        }
                                
                        seed_num++;
                }
                
                pos += thread_num;
        }
        
        std::sort(mySamples.begin(), mySamples.end(), moreVNSAMPLE);
        for(i = 0; i < mySamples[0].DFF_ids.size(); i++)       
        {
                int id = mySamples[0].DFF_ids[i];
                Ci->getFlipflop(id)->getOutput(0)->chosen = true;       
        }
}


void Simulate::greedyAddIslands(vector<int> &selected_traces){
        
        int i, j, k, pos = 0;
        
        k = islands.size();
        const int tot_thread_num = islands.size();
        //cout<< "island's size is " << tot_thread_num << endl;

        vector<sample> mySamples;
        while(k > 0){
                
                int thread_num;
                if(k / THREAD_NUM_T >= 1)
                        thread_num = THREAD_NUM_T;
                else
                        thread_num = k % THREAD_NUM_T;
                
                pthread_t PTs[thread_num];
                
                for(j = 0; j < thread_num; j++)
                {
                        sample MS;
                        for(i=0; i < Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                
                        for(i=0; i < selected_traces.size(); ++i)
                                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                
                        Ci->getFlipflop(islands[pos + j])->getOutput(0)->setTraced(true,j);
                
                        MS.VN = 0.0;
                        MS.DFF_ids.push_back(islands[pos + j]);
                        mySamples.push_back(MS);
                }
        
                int seed_num = 0;
                while(seed_num < 2)
                {
                        initACCMultThread(thread_num, seed_num);
                        //initMultThread(thread_num);
                
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;
                                mwa->Sim = this;
                                //LoadInitDFFValue(50 + seed_num * 150, j);
                                LoadInitDFFValue(seed_num, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                        
                                //cout<<"Tid is "<<mra->Tid + pos<<endl;
                                mySamples[pos + mra->Tid].VN += mra->VN;
                                delete mra;
                        }
                
                        seed_num++;
                }
                
                k -= thread_num;
                pos += thread_num;        
        }
        
        //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;
        assert(pos == tot_thread_num);
        std::sort(mySamples.begin(), mySamples.end(), moreVNSAMPLE);
        
        i = 1;
        //cout << "added islands flipflop num is " << i << endl;
        
        for(j = 0; j < i; j++)
        {
                selected_traces.push_back(mySamples[j].DFF_ids[0]);
                islands.erase(std::find(islands.begin(), islands.end(), mySamples[j].DFF_ids[0]));
        }
        
        for(i=0; i < Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(i=0; i < selected_traces.size(); ++i)
                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,0);
        
        int seed_num = 0;
        double VN =0.0;
        while(seed_num < 2){
                
                initMultThread(1);
                LoadInitDFFValue(seed_num,0);
                VN += MultCalVNWOLOCK(0);
                
                for(int i=0; i<Ci->signalSize(); ++i){
                        Ci->getSignal(i)->Mult_Val0_ref[seed_num] = Ci->getSignal(i)->Mult_Val0[0];
                        Ci->getSignal(i)->Mult_Val1_ref[seed_num] = Ci->getSignal(i)->Mult_Val1[0];
                }
                
                seed_num++;
        }
        cout<<"After adding islands, VN is "<< VN / 2 <<endl;
        
        //initMultThread(1);
        //LoadInitDFFValue(0,0);
        //cout<<"After adding islands, VN is "<< MultCalVNWOLOCK(0) <<endl;        
        
        double restime = 0.0;
        for(j = 0; j < Ci->flipflopSize(); ++j)
        {
                restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        }
}


void Simulate::addIslands(vector<int> &selected_traces, double VN_bar){
        
        int i, j, k, pos = 0;
        
        k = islands.size();
        const int tot_thread_num = islands.size();
        cout<< "island's size is " << tot_thread_num << endl;

        vector<sample> mySamples;
        while(k > 0){
                
                int thread_num;
                if(k / THREAD_NUM_T >= 1)
                        thread_num = THREAD_NUM_T;
                else
                        thread_num = k % THREAD_NUM_T;
                
                pthread_t PTs[thread_num];
                
                for(j = 0; j < thread_num; j++)
                {
                        sample MS;
                        for(i=0; i < Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                
                        for(i=0; i < selected_traces.size(); ++i)
                                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                
                        Ci->getFlipflop(islands[pos + j])->getOutput(0)->setTraced(true,j);
                
                        MS.VN = 0.0;
                        MS.DFF_ids.push_back(islands[pos + j]);
                        mySamples.push_back(MS);
                }
        
                int seed_num = 0;
                while(seed_num < 2)
                {
                        initACCMultThread(thread_num, seed_num);
                        //initMultThread(thread_num);
                
                        for(j = 0; j < thread_num; j++)
                        {
                                myWorkarg* mwa= new myWorkarg;
                                mwa->Tid = j;
                                mwa->Sim = this;
                                //LoadInitDFFValue(50 + seed_num * 150, j);
                                LoadInitDFFValue(seed_num, j);
                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                        }
                
                        for(j = 0; j < thread_num; j++)
                        {
                                myRetarg* mra = new myRetarg;
                                pthread_join(PTs[j], (void**) &mra);
                        
                                //cout<<"Tid is "<<mra->Tid + pos<<endl;
                                mySamples[pos + mra->Tid].VN += mra->VN;
                                delete mra;
                        }
                
                        seed_num++;
                }
                
                k -= thread_num;
                pos += thread_num;        
        }
        
        //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;
        assert(pos == tot_thread_num);
        std::sort(mySamples.begin(), mySamples.end(), moreVNSAMPLE);
        
        const double threshold = 10.0;
        for(i = 0; i < mySamples.size(); i++)       
        {
                if(mySamples[i].VN / 2 - VN_bar < threshold)
                        break;
        }
        
        if(i == 0){
                cout << "no other selected" << endl;
                return;
        }
        else
        {
                i = 1;
                cout << "added islands flipflop num is " << i << endl;
        }        
        
        
        for(j = 0; j < i; j++)
        {
                selected_traces.push_back(mySamples[j].DFF_ids[0]);
                islands.erase(std::find(islands.begin(), islands.end(), mySamples[j].DFF_ids[0]));
        }
        
        for(i=0; i < Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(i=0; i < selected_traces.size(); ++i)
                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,0);
        
        int seed_num = 0;
        double VN =0.0;
        while(seed_num < 2){
                
                initMultThread(1);
                LoadInitDFFValue(seed_num,0);
                VN += MultCalVNWOLOCK(0);
                
                for(int i=0; i<Ci->signalSize(); ++i){
                        Ci->getSignal(i)->Mult_Val0_ref[seed_num] = Ci->getSignal(i)->Mult_Val0[0];
                        Ci->getSignal(i)->Mult_Val1_ref[seed_num] = Ci->getSignal(i)->Mult_Val1[0];
                }
                
                seed_num++;
        }
        cout<<"After adding islands, VN is "<< VN / 2 <<endl;
        
        //initMultThread(1);
        //LoadInitDFFValue(0,0);
        //cout<<"After adding islands, VN is "<< MultCalVNWOLOCK(0) <<endl;        
        
        double restime = 0.0;
        for(j = 0; j < Ci->flipflopSize(); ++j)
        {
                restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
        }
}


extern int HeuTry;
void Simulate::hueristicSelect2(const int trace_size, const char* filename){
        
        int i, j, k, flag;
        double weight, temp_weight, cur_VN;
        vector<resMap*> Mymap;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        map< string, resMap* > RSmap;

        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_heu";
        
        //ofstream report(tmp.c_str());
        //report<<Ci->flipflopSize()<<endl;
        
        clock_t start1, finish1, start2, finish2;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
        
        initSimulate();
        //SimInitDFFValue();
        LoadDFFMap(filename, -1);
        start1 = clock();
        
        //finish collecting resMap
        for(i = 0; i < Ci->flipflopSize(); ++i)
        {
                flag = 0;
                resMap* MyresMap = new resMap;
                clearTraced();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(true);
                addTraced(Ci->getFlipflop(i)->getOutput(0));
                
                assert(tracedSigs.size() == 1);
                
                MyresMap->DFF_id = i;
                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->getP0();
                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->getP1();
                
                if(MyresMap->P0 == 0.0 && MyresMap->P1 == 0.0)
                {
                        cout<<"no Way!"<<endl;
                        cout<<"the signal name is "<<Ci->getFlipflop(i)->getOutput(0)->getName()<<endl;
                }
                //initSimulateGolden();
                //initSimulateHybrid();
                //sim_event(true);
                //sim_event(false);
                
                initSimulateHybrid();
                PreSimHybrid1Trace();
                
                for(k = 0; k<Ci->flipflopSize(); ++k)
                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                simHybrid1Trace(true);
                
                int count_res1 = 0;
                for(k =0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
				if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                   Ci->getFlipflop(k)->getOutput(0)->preset == false)
                                {
                                        flag = 1;
                                        MyresMap->R1.insert(k);
                                        
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getFlipflop(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;
                                        
                                        MyresMap->R1_P.push_back(RV);
                                        count_res1++;
                                }
                
                //cout<<"# of DFFs stored when "<< Ci->getFlipflop(i)->getOutput(0)->getName() << " has value 1 is "
                //<< count_res1 << endl;
                
                //initSimulateGolden();
                //initSimulateHybrid();
                //sim_event(true);
                //sim_event(false);

                initSimulateHybrid();
                PreSimHybrid1Trace();
                
                for(k = 0; k<Ci->flipflopSize(); ++k)
                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                simHybrid1Trace(false);
                
                int count_res0 = 0;
                for(k =0; k<Ci->flipflopSize(); ++k)
			if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
				if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                   Ci->getFlipflop(k)->getOutput(0)->preset == false)
                                {
                                        flag = 1;
                                        MyresMap->R0.insert(k);
                                        
                                        resVal RV;
                                        RV.DFF_id = k;
                                        if(Ci->getFlipflop(k)->getOutput(0)->getVal() == One)
                                                RV.val = 1;
                                        else
                                                RV.val = 0;

                                        MyresMap->R0_P.push_back(RV);
                                        count_res0++;
                                }
                
                //cout<<"# of DFFs stored when "<< Ci->getFlipflop(i)->getOutput(0)->getName() << " has value 0 is "
                //<< count_res0 << endl;
                
                //cin.get();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                
                if(flag == 1)
                {
                        RSmap.insert(pair<string, resMap*>(Ci->getFlipflop(i)->getOutput(0)->getName(), MyresMap) );
                        Mymap.push_back(MyresMap);
                }
                else
                        islands.push_back(i);
        }
        finish1 = clock();
        
        vector<resMap*> Mymap_Ori(Mymap);
        
        if(filename == NULL)
        {
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        cout<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;
                        cout<<"restored DFF from 0"<<endl;
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                cout<<*it_set<<"\t";
                        cout<<endl;
                        
                        cout<<"restored DFF from 1"<<endl;
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                cout<<*it_set<<"\t";
                        cout<<endl;
                }
        }
        else
        {
                cout<<"filename is "<<filename <<endl;
                //cin.get();
                ofstream out(filename);
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        out<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<Ci->getFlipflop((*it_map)->DFF_id)->getOutput(0)->getName()<<"\t"<<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;
                        out<<"restored DFF from 0 size is "<<(*it_map)->R0.size()<<endl;
                        for(it_set = (*it_map)->R0.begin(); it_set != (*it_map)->R0.end(); it_set++)
                                out<<*it_set<<"\t";
                        out<<endl;
                
                        out<<"restored DFF from 1 size is "<<(*it_map)->R1.size()<<endl;
                        for(it_set = (*it_map)->R1.begin(); it_set != (*it_map)->R1.end(); it_set++)
                                out<<*it_set<<"\t";
                        out<<endl;
                }
        }
        
        start2 = clock();
        cout<<"The time spend on generating the reachibility list is "<< ( (finish1 - start1)/CLOCKS_PER_SEC )<<endl;
        //cout<<"Should be added later!"<<endl;
        //cur_VN = huerSelect2ProcessFor1(trace_size, Mymap, selected_traces);
        cur_VN = huerSelect2ProcessFor2(trace_size, Mymap, selected_traces, tmp.c_str());
        //cur_VN = huerSelect2ProcessFor2Com(trace_size, Mymap, selected_traces, tmp.c_str());
        //cur_VN = huerSelect2ProcessFor2Mod(trace_size, Mymap, selected_traces);
        //cur_VN = huerSelect2ProcessBack(trace_size, Mymap, selected_traces);
        //cur_VN = huerSelect2ProcessBackMod(trace_size, Mymap, selected_traces);
        cout<<"Initial VN is "<<cur_VN<<endl;
        //return;

        vector<int> final_traces;
        vector<int> root_traces(selected_traces);
        /*
        vector<Signal*>::iterator it;
        cout<< "selected_traces size is "<<selected_traces.size()<<endl;
        cout<<"trace size is "<<trace_size<<endl;
        cout<<"island size is "<<islands.size()<<endl;
        
        //find the neighbour of the flipflops 
        for(int i =0 ; i < selected_traces.size(); i++)
                Ci->getFlipflop(selected_traces[i])->getOutput(0)->chosen = true;
        
        DFFSearchNearby();
        Sample_Procedure(200);
        //Sample_Procedure(200);
        //Sample_Procedure(100);
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        int count_chosen = 0;
        for(i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->chosen == true)       
                {
                        count_chosen++;
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
                }
        
        cout<<"Chosen number of flipflops is "<<count_chosen<<endl;
        
        double temp_VN;
        temp_VN = MultComputVN(0);        
        cout<< "#VN : " << temp_VN <<endl;
        return;
        */
        /*
        const int insert_num = 20;
        for(i = 0; i < insert_num; i++)
        {
                lessRSedSignals[i]->setTraced(true);
        }
        
        
        tracedSigs.clear();
        for(i = 0; i < Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced() == true)
                        tracedSigs.push_back(Ci->getFlipflop(i)->getOutput(0));
        
        Conf* c1;
        Confset* C1;
        vector<Signal*>::iterator it;
        cout<<"trace sig size is "<<tracedSigs.size()<<endl;
        cout<<"trace size is "<<trace_size<<endl;
        while(tracedSigs.size() > trace_size)
        {
                C1 = new Confset();
                for(i = 0; i < tracedSigs.size(); i++)
                {
                        tracedSigs[i]->setTraced(false);
                        c1 = new Conf();
                        c1->tracedSigs.push_back(tracedSigs[i]);
                        
                        initMultThread(1);
                        LoadInitDFFValue(0);
                        c1->TV = MultCalVN(0);
                        
                        c1->TVNC = c1->TV;
                        C1->confs.push_back(c1);
                        tracedSigs[i]->setTraced(true);
                }
                
                sort(C1->confs.begin(), C1->confs.end(), moreTV());
                assert(C1->confs.size() > 0);
                assert(C1->confs[0]->tracedSigs.size() == 1);
                
                it = find(tracedSigs.begin(), tracedSigs.end(), C1->confs[0]->tracedSigs[0]);
                assert( it != tracedSigs.end() );
                
                (*it)->setTraced(false);
                tracedSigs.erase(it);
                
                C1->~Confset();
        }
        
        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
        {
                cout<<(*it)->getName()<<"\t";
        }
        cout<<endl;
        */
        
        double temp_VN = cur_VN;
        //temp_VN = computVN();
        //temp_VN = MultComputVN(0);
        //temp_VN = exhaustiveComputVN(true);
        cout<< "#VN : " << temp_VN <<endl;
        
        //addIslands(selected_traces, temp_VN);

        /*
        double temp_P;
        int j = 0;
        for(it_vec = root_traces.begin(); it_vec != root_traces.end() && j <= HeuTry; it_vec++){
                
                j++; i = 0;
                selected_traces.clear();
                Mymap = Mymap_Ori;
                
                for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                        if((*it_map)->DFF_id == *it_vec)
                        {
                                it_map1 = it_map;
                                break;
                        }
                
                while(i != trace_size)
                {
                        i++;
                        //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;
                        selected_traces.push_back((*it_map1)->DFF_id);
                        for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                        {
                                if(it_map != it_map1)
                                {
                                        for(it_set = (*it_map1)->R0.begin(); it_set != (*it_map1)->R0.end(); it_set++)
                                        {
                                                //if the DFF can be
                                                //restored from both 0 and 1
                                                if((*it_map)->R1.find(*it_set) != (*it_map)->R1.end() )
                                                        temp_P = 1;
                                                else
                                                        temp_P = (*it_map1)->P0;
                                                
                                                it_set1 = (*it_map)->R0.find(*it_set);                                                                
                                                if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= temp_P)
                                                        (*it_map)->R0.erase(it_set1);
                                                
                                                it_set1 = (*it_map)->R1.find(*it_set);
                                                if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= temp_P)
                                                        (*it_map)->R1.erase(it_set1);
                                                
                                        }
                                        
                                        for(it_set = (*it_map1)->R1.begin(); it_set != (*it_map1)->R1.end(); it_set++)
                                        {
                                                if((*it_map)->R0.find(*it_set) != (*it_map)->R0.end() )
                                                        temp_P = 1;
                                                else
                                                        temp_P = (*it_map1)->P1;
                                                
                                                it_set1 = (*it_map)->R1.find(*it_set);
                                                if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= temp_P)
                                                        (*it_map)->R1.erase(it_set1);
                                
                                                it_set1 = (*it_map)->R0.find(*it_set);
                                                if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= temp_P)
                                                        (*it_map)->R0.erase(it_set1);
                                        }
                                }
                        }
                        
                        Mymap.erase(it_map1);
                        
                        weight = 0.0;
                        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                        {
                                temp_weight = (*it_map)->R0.size() * (*it_map)->P0 + 
                                        (*it_map)->R1.size() * (*it_map)->P1;
                        
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                        }
                
                        if(weight == 0.0)
                                break;
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
                
                tracedSigs.clear();
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                        tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
                }
                
                //double temp_VN = computVN();
                //double temp_VN = exhaustiveComputVN();
                initMultThread(1);
                LoadInitDFFValue(0,0);
                double temp_VN = MultCalVNWOLOCK(0);
                //double temp_VN = MultComputVN(0);
                if(temp_VN > cur_VN)
                {
                        cur_VN = temp_VN;
                        swap(final_traces,selected_traces);
                }
        }
        finish2 = clock();
        */
        /*
        report<<"total runtime for DFF Simulation is: "<<( (finish1 - start1)/CLOCKS_PER_SEC )<<endl;
        report<<"total runtime for Heuristic Selection is: "<<( (finish2 - start2)/CLOCKS_PER_SEC )<<endl;
        report<<final_traces.size()<<endl;
        report<<"seleted signals are...."<<endl;
        
        cout<<"seleted signals are...."<<endl;
        for(it_vec = final_traces.begin(); it_vec != final_traces.end(); it_vec++)
        {
        report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
        cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
        }
        cout<<endl;
        report<<endl;
        
        report<<selected_traces.size()<<endl;
        cout<<"seleted signals are...."<<endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
        {
                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
        }
        cout<<endl;
        report<<endl;
        
        cout<<"Visibility is "<<cur_VN<<endl;
        report<<cur_VN<<endl;
        report.close();
        */
}

bool lessRestoredMap(resMap* a1, resMap *a2)
{
        return (a1->R.size() < a2->R.size());
}

void Simulate::hueristicSelect3(const int trace_size, const char* filename){
        
        int i, j, k, flag;
        double weight, temp_weight, cur_VN;
        vector<resMap*> Mymap;
        vector<resMap*>::iterator it_map;
        vector<resMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        map< string, resMap* > RSmap;
        
        map<int,double>::iterator it_RM;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        i = 0;
        while(tmp.c_str()[i] != 'b')
                i++;
        tmp.erase(tmp.begin()+i,tmp.end());
        tmp += "report_heu";
        
        ofstream report(tmp.c_str());
        report<<Ci->flipflopSize()<<endl;
        
        clock_t start1, finish1, start2, finish2;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
        
        //PickTop3MostFanout();
        
        initSimulate();
        SimInitDFFValue();
        //SetProb();
        start1 = clock();
        //finish collecting resMap
        cout<<"FLipflop size is "<<Ci->flipflopSize()<<endl;
        for(i = 0; i < Ci->flipflopSize(); ++i)
        {
                flag = 0;
                resMap* MyresMap = new resMap;
                clearTraced();
                Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
                addTraced(Ci->getFlipflop(i)->getOutput(0));
                
                assert(tracedSigs.size() == 1);
                
                MyresMap->DFF_id = i;
                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->getP0();
                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->getP1();
                
                if(MyresMap->P0 == 0.0 && MyresMap->P1 == 0.0)
                {
                        cout<<"no Way!"<<endl;
                        cout<<"the signal name is "<<Ci->getFlipflop(i)->getOutput(0)->getName()<<endl;
                }
                
                initMultThread(1);
                LoadInitDFFValue(0,0);
                MultCalVN(0);
                
                //int count_res1 = 0;
                int restime = 0;
                for(k =0; k<Ci->flipflopSize(); ++k)
                {
                        if(Ci->getFlipflop(k)->getOutput(0)->getTraced(0) == true)
                                continue;
                        
                        restime = Ci->getFlipflop(k)->getOutput(0)->isMultKnown(0);
                        if(restime != 0)
                        {
                                flag = 1;
                                MyresMap->R[k] = (double)restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                                //count_res1++;
                        }
                }
                
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
                
                if(flag == 1)
                {
                        RSmap.insert(pair<string, resMap*>(Ci->getFlipflop(i)->getOutput(0)->getName(), MyresMap) );
                        Mymap.push_back(MyresMap);
                }
                else
                        islands.push_back(i);
        }
        finish1 = clock();
        
        vector<resMap*> Mymap_Ori(Mymap);
        /*
        if(filename == NULL)
        {

        }
        else
        {
                cout<<"filename is "<<filename <<endl;
                //cin.get();
                ofstream out(filename);
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        out<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<"Name\t" << Ci->getFlipflop((*it_map)->DFF_id)->getOutput(0)->getName()<<"\t"
                           <<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;
                        out<<"restored DFF size is "<<(*it_map)->R.size()<<endl;
                        for(it_RM = (*it_map)->R.begin(); it_RM != (*it_map)->R.end(); it_RM++)
                                out<<(*it_RM).first<<"\t";
                        out<<endl;
                
                }
        }
        */
        start2 = clock();
        cur_VN = huerSelect3Process(trace_size, Mymap, selected_traces);
        cout<<"Initial VN is "<<cur_VN<<endl;
        /*
        for(i = 0; i < Ci->flipflopSize(); ++i)
        {
                if(Ci->getFlipflop(i)->getOutput(0)->getTraced(0) == true)
                {
                        for(int j = 0; j < 8*sizeof(myDataType); j++)
                                cout<<Ci->getFlipflop(i)->getOutput(0)->valArray[j]<<"\t";
                        cout<<endl;
                }
        }
        cin.get();
        */
        
        // double temp_VN;
        // int count = 0;
        // while(1)
        // {
        //         updateRStime();
        //         Mymap = Mymap_Ori;
        //         updateRSmapWeight(Mymap);
        //         std::sort(Mymap.begin(), Mymap.end(), moreRSWeight);
                
        //         for(int i = 0; i < Mymap.size(); i++)
        //                 if(Ci->getFlipflop(Mymap[i]->DFF_id)->getOutput(0)->getTraced(0) == false)
        //                 {
        //                         cout<<"added flipflop name is "
        //                             <<Ci->getFlipflop(Mymap[i]->DFF_id)->getOutput(0)->getName()<<endl;
        //                         Ci->getFlipflop(Mymap[i]->DFF_id)->getOutput(0)->setTraced(true,0);
        //                         break;
        //                 }
                
        //         //initMultThread(1);
        //         LoadInitDFFValue(0,0);
        //         temp_VN = MultCalVNWOLOCK(0);
        //         cout<<"temp_VN is "<<temp_VN<<endl;
                
        //         count++;
        //         if(count == 40)
        //                 break;
        //         /*
        //         if(temp_VN > cur_VN)
        //                 cur_VN = temp_VN;
        //         else
        //                 break;
        //         */
        // }
        
        // temp_VN = MultComputVN(0);
        // cout<<"#VN is "<<temp_VN<<endl;
        
        vector<int> final_traces;
        vector<int> root_traces(selected_traces);
        
        Conf* c1;
        Confset* C1;
        vector<Signal*>::iterator it;
        cout<<"trace sig size is "<<tracedSigs.size()<<endl;
        cout<<"trace size is "<<trace_size<<endl;
        cout<<"island size is "<<islands.size()<<endl;
        
        //find the neighbour of the flipflops 
        for(int i =0 ; i < selected_traces.size(); i++)
                tracedSigs[i]->chosen = true;
        
        DFFSearchNearby();
        Sample_Procedure(100);
        //Sample_Procedure(100);
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                if(Ci->getFlipflop(i)->getOutput(0)->chosen == true)       
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
        
        double temp_VN;
        temp_VN = MultComputVN(0);        
        cout<< "#VN : " << temp_VN <<endl;
        return;
        
        for(i = 0; i < Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        tracedSigs.clear();
        for(int i =0 ; i < selected_traces.size(); i++)
        {
                tracedSigs.push_back(Ci->getFlipflop(selected_traces[i])->getOutput(0));
                tracedSigs[i]->setTraced(true,0);
        }
        
        Mymap = Mymap_Ori;
        std::sort(Mymap.begin(), Mymap.end(), lessRestoredMap);
        
        /*
        i = 0;
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
        {
                tracedSigs.push_back(Ci->getFlipflop((*it_map)->DFF_id)->getOutput(0));
                tracedSigs[i]->setTraced(true,0);
                i++;
        }
        
        for(int i =0 ; i < islands.size(); i++)
        {
                tracedSigs.push_back(Ci->getFlipflop(islands[i])->getOutput(0));
                tracedSigs[i]->setTraced(true,0);
                }
        */
        /*
        while(tracedSigs.size() > trace_size)
        {
                C1 = new Confset();
                for(i = 0; i < tracedSigs.size(); i++)
                {
                        tracedSigs[i]->setTraced(false,0);
                        c1 = new Conf();
                        c1->tracedSigs.push_back(tracedSigs[i]);
                        initMultThread(1);
                        LoadInitDFFValue(0,0);
                        c1->TV = MultCalVN(0);
                        //c1->TV = MultComputVN();
                        c1->TVNC = c1->TV;
                        C1->confs.push_back(c1);
                        tracedSigs[i]->setTraced(true,0);
                }
                
                sort(C1->confs.begin(), C1->confs.end(), moreTV());
                assert(C1->confs.size() > 0);
                assert(C1->confs[0]->tracedSigs.size() == 1);
                
                cout<<"current trace size "<<tracedSigs.size()
                    <<" VN "<< C1->confs[0]->TV << endl;
                      
                it = find(tracedSigs.begin(), tracedSigs.end(), C1->confs[0]->tracedSigs[0]);
                assert( it != tracedSigs.end() );
                
                (*it)->setTraced(false,0);
                tracedSigs.erase(it);
                
                C1->~Confset();
        }
        
        for(i = 0; i < Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
        
        for(it = tracedSigs.begin(); it != tracedSigs.end(); it++)
        {
                (*it)->setTraced(true,0);
                cout<<(*it)->getName()<<"\t";
        }
        cout<<endl;        
        */
        
        double temp_P;
        j = 0;
        for(it_vec = root_traces.begin(); it_vec != root_traces.end() && j <= HeuTry; it_vec++){
                
                j++; i = 0;
                selected_traces.clear();
                Mymap = Mymap_Ori;
                
                for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                        if((*it_map)->DFF_id == *it_vec)
                        {
                                it_map1 = it_map;
                                break;
                        }
                
                while(i != trace_size)
                {
                        i++;
                        //cout<<"Choosen flipflop is "<< (*it_map1)->DFF_id <<endl;
                        selected_traces.push_back((*it_map1)->DFF_id);
                        for(it_map = Mymap.begin(); it_map != Mymap.end(); it_map++)
                        {
                                if(it_map != it_map1)
                                {
                                        for(it_set = (*it_map1)->R0.begin(); it_set != (*it_map1)->R0.end(); it_set++)
                                        {
                                                //if the DFF can be
                                                //restored from both 0 and 1
                                                if((*it_map)->R1.find(*it_set) != (*it_map)->R1.end() )
                                                        temp_P = 1;
                                                else
                                                        temp_P = (*it_map1)->P0;
                                                
                                                it_set1 = (*it_map)->R0.find(*it_set);                                                                
                                                if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= temp_P)
                                                        (*it_map)->R0.erase(it_set1);
                                                
                                                it_set1 = (*it_map)->R1.find(*it_set);
                                                if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= temp_P)
                                                        (*it_map)->R1.erase(it_set1);
                                                
                                        }
                                        
                                        for(it_set = (*it_map1)->R1.begin(); it_set != (*it_map1)->R1.end(); it_set++)
                                        {
                                                if((*it_map)->R0.find(*it_set) != (*it_map)->R0.end() )
                                                        temp_P = 1;
                                                else
                                                        temp_P = (*it_map1)->P1;
                                                
                                                it_set1 = (*it_map)->R1.find(*it_set);
                                                if(it_set1 != (*it_map)->R1.end() && (*it_map)->P1 <= temp_P)
                                                        (*it_map)->R1.erase(it_set1);
                                
                                                it_set1 = (*it_map)->R0.find(*it_set);
                                                if(it_set1 != (*it_map)->R0.end() && (*it_map)->P0 <= temp_P)
                                                        (*it_map)->R0.erase(it_set1);
                                        }
                                }
                        }
                        
                        Mymap.erase(it_map1);
                        
                        weight = 0.0;
                        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                        {
                                temp_weight = (*it_map)->R0.size() * (*it_map)->P0 + 
                                        (*it_map)->R1.size() * (*it_map)->P1;
                        
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                        }
                
                        if(weight == 0.0)
                                break;
                }
                
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);
                
                tracedSigs.clear();
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                        tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
                }
                
                //double temp_VN = computVN();
                //double temp_VN = exhaustiveComputVN();
                initMultThread(1);
                LoadInitDFFValue(0,0);
                double temp_VN = MultCalVN(0);
                
                if(temp_VN > cur_VN)
                {
                        cur_VN = temp_VN;
                        swap(final_traces,selected_traces);
                }
        }
        
        finish2 = clock();
        
        report<<"total runtime for DFF Simulation is: "<<( (finish1 - start1)/CLOCKS_PER_SEC )<<endl;
        report<<"total runtime for Heuristic Selection is: "<<( (finish2 - start2)/CLOCKS_PER_SEC )<<endl;
        report<<final_traces.size()<<endl;
        report<<"seleted signals are...."<<endl;
        
        cout<<"seleted signals are...."<<endl;
        for(it_vec = final_traces.begin(); it_vec != final_traces.end(); it_vec++)
        {
                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
        }
        cout<<endl;
        report<<endl;
        
        cout<<"Visibility is "<<cur_VN<<endl;
        report<<cur_VN<<endl;
        
}

double Simulate::Check_Traces(const int trace_size)
{
        int cur_size = 0;
        string name;
        clearTraced();
        
        cout<<"Begin inputing traced flipflops...."<<endl;
        while(cur_size < trace_size)
        {
                std::getline(cin,name);
                for(int i=0; i<Ci->flipflopSize(); ++i)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == name)
                        {
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
                                addTraced(Ci->getFlipflop(i)->getOutput(0));
                        }
                }
                cout<<"Another one..."<<endl;
                cur_size++;
        }
        cout<<"Inputing done!"<<endl;
        //double visibility = computVN();
        //double visibility = exhaustiveComputVN();
        initSimulate();
        SimInitDFFValue();

        double total_VN = 0.0;
        int seed_num = 3;
        for(int i = 0; i < seed_num; i++)
        {
                initMultThread(1);
                LoadInitDFFValue(50 + seed_num * 150, 0);
                total_VN += MultCalVN(0);
        }
        
        return total_VN / 3;
}

double Simulate::Check_Traces(const int trace_size, string &filename)
{
        int cur_size = 0;
        /*
        string name;
        clearTraced();
        cout<<"Begin inputing traced flipflops...."<<endl;
        while(cur_size < trace_size)
        {
        std::getline(cin,name);
        for(int i=0; i<Ci->flipflopSize(); ++i)
                {
                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == name)
                        {
                               Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
                                addTraced(Ci->getFlipflop(i)->getOutput(0));
                        }
                }
                cout<<"Another one..."<<endl;
                cur_size++;
        }
        
        cout<<"Inputing done!"<<endl;
        */
        
        if(!filename.empty())
        {
                string key ("bench");
                size_t found;

                found=filename.rfind(key);
                if (found!=string::npos)
                        filename.replace(found,key.length(),"report_greedy32");
                        //filename.replace (found,key.length(),"report_heu");
                        //filename.replace(found,key.length(),"report_prune");
                        //filename.replace (found,key.length(),"bench.32.traces");
                
                cout<<"filename is "<<filename<<endl;
        }
        
        ifstream in(filename.c_str());
        const int MAX_LINE_LENGTH = 65536;
        char line_buffer[MAX_LINE_LENGTH];
 
        while(1)
        {
                in.getline(line_buffer, MAX_LINE_LENGTH);
                char* p = strtok(line_buffer, "\t\n");
                if(!strcmp(p, "32"))
                        break;
        }
        in.getline(line_buffer, MAX_LINE_LENGTH);
        in.getline(line_buffer, MAX_LINE_LENGTH);
        
        char* s = strtok(line_buffer, "\t\n");
        vector<int> traced_dff_ids;
        
        while(s != NULL)
        {
                cout<<s<<endl;
                int flag = 0;
                for(int i=0; i<Ci->flipflopSize(); ++i)
                        if(!strcmp(Ci->getFlipflop(i)->getOutput(0)->getName().c_str(),s))
                        {
                                flag = 1;
                                traced_dff_ids.push_back(i);
                                break;
                        }
                
                assert(flag == 1);
                s = strtok(NULL, "\t\n");
        }
        
        cout<<traced_dff_ids.size()<<endl;
        assert(traced_dff_ids.size() == 32);
        in.close();
        
        initSimulate();
        SimInitDFFValue();
        
        double total_vis = 0;
        const int seed_num = 3;
        const int trace_type = 3;
        pthread_t PTs[trace_type * seed_num];
        
        initMultithread_GREEDY(trace_type * seed_num);
        initMultThread(trace_type * seed_num);
        
        for(int j = 0; j < trace_type; j++)
        {
                for(int i = 0; i < seed_num; i++)
                {
                        if(j == 0)
                                for(int k = 0; k < 8; k++)
                                        Ci->getFlipflop(traced_dff_ids[k])->getOutput(0)->setTraced(true, j * trace_type + i);
                        else if(j == 1)
                                for(int k = 0; k < 16; k++)
                                        Ci->getFlipflop(traced_dff_ids[k])->getOutput(0)->setTraced(true, j * trace_type + i);
                        else
                                for(int k = 0; k < 32; k++)
                                        Ci->getFlipflop(traced_dff_ids[k])->getOutput(0)->setTraced(true, j * trace_type + i);
                        
                        myWorkarg* mwa= new myWorkarg;
                        mwa->Tid = j * trace_type + i;//should add pos later
                        mwa->Sim = this;
                        LoadInitDFFValue(50 + seed_num * 150,j * trace_type + i);
                        pthread_create(&PTs[j * trace_type + i], NULL, work, (void*)mwa);
                }
        }
        
        double Tvis[trace_type];
        memset(Tvis, 0.0, sizeof(double) * trace_type);

        for(int i = 0; i < trace_type * seed_num; i++)
        {
                myRetarg* mra = new myRetarg;
                pthread_join(PTs[i], (void**) &mra);
                
                Tvis[i/seed_num] += mra->VN;
                delete mra;
        }
        
        for(int i = 0; i < trace_type; i++)
        {
                if(i == 0)
                        cout<<"Total Vis for 8 is "<<Tvis[i]/seed_num <<endl;
                else if(i == 1)
                        cout<<"Total Vis for 16 is "<<Tvis[i]/seed_num <<endl;
                else
                        cout<<"Total Vis for 32 is "<<Tvis[i]/seed_num <<endl;
        }
        
        return 0.0;
}


int Simulate::findLongestPathFlipflop(int DFF_id){
}


int backTrackPathInfo(vector<Node*>& Path, int dir, map<int, int> &R_seq_res_len){
        
        //cout << "Path size is " << Path.size() << endl;
        for(int i = 0; i < Path.size(); i++)
                Path[i]->level = -1;
                
        //front is the sink
        Node* temp = Path.front();
        int sink_DFF_id = ((FlipflopNode*)(temp))->FF_index;
        
        temp->level = 0;
        
        if(dir == 1){
                for(int i = 0; i < Path.size(); i++){
                        bool test = false;
                        Node* cur_gate = Path[i];
                        for(int k = 0; k < cur_gate->outputSize(); k++){
                                for(int j = 0; j < cur_gate->getOutput(k)->outputSize(); j++){
                                        vector<Node*>:: iterator it_path;
                                        for(it_path = Path.begin() + i + 1; it_path != Path.end(); it_path++)
                                                if(*it_path == cur_gate->getOutput(k)->getOutput(j)){
                                                        test = true;
                                                        (*it_path)->level = cur_gate->level + 1;
                                                }
                                }
                        }
                
                        if(test == false)
                                cur_gate->level = -1;
                }
        }
        else{
                for(int i = 0; i < Path.size(); i++){
                        bool test = false;
                        Node* cur_gate = Path[i];
                        for(int k = 0; k < cur_gate->inputSize(); k++){
                                for(int j = 0; j < cur_gate->getInput(k)->inputSize(); j++){
                                        vector<Node*>:: iterator it_path;
                                        for(it_path = Path.begin() + i + 1; it_path != Path.end(); it_path++)
                                                if(*it_path == cur_gate->getInput(k)->getInput(j)){
                                                        test = true;
                                                        (*it_path)->level = cur_gate->level + 1;
                                                }
                                }
                        }
                
                        if(test == false)
                                cur_gate->level = -1;
                }
        }
        
        int count_restored = 0;
        int count_gate = 0;
        vector<Node*> real_Path;
        if(dir == 1){//source inputs to sink
                for(int i = 1; i < Path.size() - 1; i++){
                        if(Path[i]->level != -1){
                                count_gate++;
                                bool test = true;
                                for(int k = 0; k < Path[i]->inputSize(); k++){
                                        if(Path[i]->getInput(k)->isKnown() == false){
                                                test = false;
                                                break;
                                        }
                                }
                                
                                if(test == true)
                                        count_restored++;
                        }
                }
        }
        else{//source outputs to sink
                for(int i = 1; i < Path.size() - 1; i++){
                        if(Path[i]->level != -1){
                                count_gate++;
                                //find unrestored gates!!!
                                if(Path[i]->getOutput(0)->isKnown() == false)
                                        count_restored++;
                        }
                }
        }
        
        R_seq_res_len[sink_DFF_id] = count_restored;
        //cout << "gate restored on the path is " << count_restored << endl;
        //cout << "gate count on the path is " << count_gate << endl;
        assert(count_gate != 0);
        return count_gate;
}


int Simulate::findPathInfo(int source_DFF_id, int sink_DFF_id, map<int, int> &R_seq_res_len){
        
        int k, found = 0;
        set<int> vicinity_DFFs;
        list<Node*> myList;//only contains gate ids
        vector<Node*> Path;
        
        for(k = 0; k<Ci->flipflopSize(); ++k)
                ((Node*)Ci->getFlipflop(k))->traversed = 0;
        
        for(k = 0; k<Ci->gateSize(); ++k)
                Ci->getGate(k)->traversed = 0;
        
        for(k = 0; k<Ci->inputSize(); ++k)
                Ci->getInput(k)->traversed = 0;
        
        for(k = 0; k<Ci->outputSize(); ++k)
                Ci->getOutput(k)->traversed = 0;
                
        Path.push_back((Node*)(Ci->getFlipflop(sink_DFF_id)));
        const int init_numbering = Ci->getFlipflop(sink_DFF_id)->numbering;
        //cout << "Init numbering is " << init_numbering << endl;
        
        for(k = 0; k < Ci->getFlipflop(sink_DFF_id)->getOutput(0)->outputSize(); k++){
                if(Ci->getFlipflop(sink_DFF_id)->getOutput(0)->getOutput(k)->signature() != FLIPFLOP){
                        if(Ci->getFlipflop(sink_DFF_id)->getOutput(0)->getOutput(k)->numbering == Ci->getFlipflop(sink_DFF_id)->numbering){
                                Path.push_back(Ci->getFlipflop(sink_DFF_id)->getOutput(0)->getOutput(k));
                                myList.push_back(Ci->getFlipflop(sink_DFF_id)->getOutput(0)->getOutput(k));
                        }
                }
                //else if(Ci->getFlipflop(sink_DFF_id)->getOutput(0)->getOutput(k)->signature() == FLIPFLOP)
                //cout << "Sp case 0 " << ((FlipflopNode*)(Ci->getFlipflop(sink_DFF_id)->getOutput(0)->getOutput(k)))->FF_index << endl;
        }
        
        //cout << "SEE " << myList.size() << endl;
        int cnt_restored = 0;
        
        while(!myList.empty())
        {
                //int cur_gate_id = myList.front();
                Node* cur_gate = myList.front();
                if(cur_gate->traversed == 1){
                        myList.pop_front();
                        continue;
                }
                
                assert(cur_gate->numbering < 1000);
                
                multimap<int, Node*> myMultiMap;
                //find the one that has the smallest numbering
                //Node* c_node = NULL; int small_numbering = -1;
                for(k = 0; k < cur_gate->outputSize(); k++){
                        for(int j = 0; j < cur_gate->getOutput(k)->outputSize(); j++){
                                if(cur_gate->getOutput(k)->getOutput(j)->signature() == FLIPFLOP){
                                        if(((FlipflopNode*)(cur_gate->getOutput(k)->getOutput(j)))->FF_index == source_DFF_id){
                                                Path.push_back(cur_gate->getOutput(k)->getOutput(j));
                                                found = 1;        
                                                break;
                                        }
                                }
                                else{
                                        if(cur_gate->getOutput(k)->getOutput(j)->numbering <= max(0, cur_gate->numbering)){
                                                myMultiMap.insert(std::make_pair(cur_gate->getOutput(k)->getOutput(j)->numbering, cur_gate->getOutput(k)->getOutput(j)));
                                                /*
                                                if(small_numbering < cur_gate->getOutput(k)->getOutput(j)->numbering){
                                                        c_node = cur_gate->getOutput(k)->getOutput(j);
                                                        small_numbering = cur_gate->getOutput(k)->getOutput(j)->numbering;
                                                }
                                                */
                                        }
                                }
                        }
                }
                
                if(found == 1)
                        break;
                
                if(myMultiMap.empty()){
                }
                else{
                        std::multimap<int, Node*>::reverse_iterator rit;
                        rit=myMultiMap.rbegin();
                        int max = (*rit).first;
                        Path.push_back((*rit).second);
                        myList.push_back((*rit).second);
                        rit++;
                        for (; rit!=myMultiMap.rend(); ++rit){
                                if((*rit).first == max){
                                        Path.push_back((*rit).second);
                                        myList.push_back((*rit).second);
                                }
                                else
                                        break;
                        }
                }
                
                /*
                if(c_node == NULL){
                        myList.clear();
                        break;
                }
                else{
                        Path.push_back(c_node);
                        myList.push_back(c_node);
                }
                */
                cur_gate->traversed++;
                myList.pop_front();        
        }
        
        if(found == 1){
                return backTrackPathInfo(Path, 1, R_seq_res_len);
        }
        else{
                Path.clear();
                for(k = 0; k<Ci->flipflopSize(); ++k)
                        ((Node*)Ci->getFlipflop(k))->traversed = 0;
                
                for(k = 0; k<Ci->gateSize(); ++k)
                        Ci->getGate(k)->traversed = 0;
                
                for(k = 0; k<Ci->inputSize(); ++k)
                        Ci->getInput(k)->traversed = 0;
        
                for(k = 0; k<Ci->outputSize(); ++k)
                        Ci->getOutput(k)->traversed = 0;
        
        }
        
        cnt_restored = 0;
        Path.push_back((Node*)(Ci->getFlipflop(sink_DFF_id)));
        for(k = 0; k < Ci->getFlipflop(sink_DFF_id)->getInput(1)->inputSize(); k++){
                if(Ci->getFlipflop(sink_DFF_id)->getInput(1)->getInput(k)->signature() != FLIPFLOP){
                        if(Ci->getFlipflop(sink_DFF_id)->getInput(1)->getInput(k)->numbering == Ci->getFlipflop(sink_DFF_id)->numbering){
                                Path.push_back(Ci->getFlipflop(sink_DFF_id)->getInput(1)->getInput(k));
                                myList.push_back(Ci->getFlipflop(sink_DFF_id)->getInput(1)->getInput(k));
                        }
                }
                //else if(Ci->getFlipflop(sink_DFF_id)->getInput(1)->getInput(k)->signature() == FLIPFLOP)
                //cout << "Sp case 1 " << ((FlipflopNode*)(Ci->getFlipflop(sink_DFF_id)->getInput(1)->getInput(k)))->FF_index << endl;
        }
        
        //cout << "SEE " << myList.size() << endl;
        while(!myList.empty())
        {
                Node* cur_gate = myList.front();
                if(cur_gate->traversed == 1){
                        myList.pop_front();
                        continue;
                }
                
                assert( cur_gate->numbering < 1000);
                multimap<int, Node*> myMultiMap;
                //find the one that has the smallest numbering
                //Node* c_node = NULL;  int small_numbering = -1;
                for(k = 0; k < cur_gate->inputSize(); k++){
                        for(int j = 0; j < cur_gate->getInput(k)->inputSize(); j++){
                                if(cur_gate->getInput(k)->getInput(j)->signature() == FLIPFLOP){
                                        if(((FlipflopNode*)(cur_gate->getInput(k)->getInput(j)))->FF_index == source_DFF_id){
                                                Path.push_back(cur_gate->getInput(k)->getInput(j));
                                                found = 1;        
                                                break;
                                        }
                                }
                                else{
                                        if(cur_gate->getInput(k)->getInput(j)->numbering <= max(0, cur_gate->numbering)){
                                                myMultiMap.insert(std::make_pair(cur_gate->getInput(k)->getInput(j)->numbering, cur_gate->getInput(k)->getInput(j)));
                                                /*
                                                  if(small_numbering < cur_gate->getInput(k)->getInput(j)->numbering){
                                                        c_node = cur_gate->getInput(k)->getInput(j);
                                                        small_numbering = cur_gate->getInput(k)->getInput(j)->numbering;
                                                }
                                                */
                                        }
                                }
                        }
                }
                
                if(found == 1)
                        break;
                
                if(myMultiMap.empty()){
                }
                else{
                        std::multimap<int, Node*>::reverse_iterator rit;
                        rit = myMultiMap.rbegin();
                        Path.push_back((*rit).second);
                        int max = (*rit).first;
                        myList.push_back((*rit).second);
                        rit++;
                        for (; rit!=myMultiMap.rend(); ++rit){
                                if((*rit).first == max){
                                        Path.push_back((*rit).second);
                                        myList.push_back((*rit).second);
                                }
                                else
                                        break;
                        }
                }
                
                /*
                if(c_node == NULL){
                        Path.clear();
                        myList.clear();
                        break;
                }
                else{
                        Path.push_back(c_node);
                        myList.push_back(c_node);    
                }
                */
                cur_gate->traversed++;
                myList.pop_front();
        }
        
        //assert(found == 1);
        if(found == 1){
                return backTrackPathInfo(Path, 0, R_seq_res_len);
        }
        else{
                //cout << "OH NO" << endl;
                return -1;
        }
}


extern int ext_logic_level;
double Simulate::findAvgLength(int DFF_id, TresMap* TM, int key){
        //cout << "Find pgath length for: " << DFF_id << "\t" << key << endl;
        int k;
        set<int> vicinity_DFFs;
        queue<Node*> myQueue;//only contains gate ids
        
        for(k = 0; k<Ci->flipflopSize(); ++k){
                if(k != DFF_id){
                        ((Node*)Ci->getFlipflop(k))->traversed = 0;
                        ((Node*)Ci->getFlipflop(k))->numbering = 1000;
                }
                else{
                        ((Node*)Ci->getFlipflop(k))->traversed = 0;
                        ((Node*)Ci->getFlipflop(k))->numbering = 0;
                }
        }
        
        for(k = 0; k<Ci->gateSize(); ++k) 
        {
                Ci->getGate(k)->traversed = 0;
                Ci->getGate(k)->numbering = 1000;
        }
        
        for(k = 0; k<Ci->inputSize(); ++k){
                Ci->getInput(k)->traversed = 0;
                Ci->getInput(k)->numbering = 1000;
        }
        
        for(k = 0; k<Ci->outputSize(); ++k){
                Ci->getOutput(k)->traversed = 0;
                Ci->getOutput(k)->numbering = 1000;
        }
        
        for(k = 0; k < Ci->getFlipflop(DFF_id)->getOutput(0)->outputSize(); k++){
                if(Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->signature() != FLIPFLOP){
                        Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->numbering = 0;
                        myQueue.push(Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k));
                }
        }
        
        while(!myQueue.empty())
        {
                //int cur_gate_id = myQueue.front();
                Node* cur_gate = myQueue.front();
                
                //cout << "current gate id is " << cur_gate_id << endl;
                for(k = 0; k < cur_gate->outputSize(); k++){
                        for(int j = 0; j < cur_gate->getOutput(k)->outputSize(); j++){
                                int flag = 0;
                                if(cur_gate->getOutput(k)->getOutput(j)->signature() == FLIPFLOP){
                                        cur_gate->getOutput(k)->getOutput(j)->numbering = cur_gate->numbering;
                                        if(cur_gate->getOutput(0)->getName() == cur_gate->getOutput(k)->getOutput(j)->getInput(1)->getName())
                                                vicinity_DFFs.insert(((FlipflopNode*)(cur_gate->getOutput(k)->getOutput(j)))->FF_index);
                                }
                                else{
                                        if(cur_gate->getOutput(k)->getOutput(j)->outputSize() && cur_gate->getOutput(k)->getOutput(j)->getOutput(0)->isKnown() == false)
                                                flag = 1;
                                
                                        int old_numbering = cur_gate->getOutput(k)->getOutput(j)->numbering;
                                        if(flag == 1)
                                                cur_gate->getOutput(k)->getOutput(j)->numbering = 
                                                        min(cur_gate->getOutput(k)->getOutput(j)->numbering, (cur_gate->numbering + 1));
                                        else
                                                cur_gate->getOutput(k)->getOutput(j)->numbering =
                                                        min(cur_gate->getOutput(k)->getOutput(j)->numbering, cur_gate->numbering);
                                        
                                        assert(cur_gate->getOutput(k)->getOutput(j)->numbering < 1000);
                                        if(old_numbering != cur_gate->getOutput(k)->getOutput(j)->numbering)
                                                myQueue.push(cur_gate->getOutput(k)->getOutput(j));
                                }
                        }
                }
                
                myQueue.pop();
        }
        
        
        for(k = 0; k < Ci->getFlipflop(DFF_id)->getInput(1)->inputSize(); k++){
                if(Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->signature() != FLIPFLOP){
                        int j;
                        for(j = 0; j < Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->inputSize(); j++)
                                if(Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->getInput(j)->isKnown() == false)
                                        break;
                        
                        if(j == Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->inputSize())
                                Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->numbering = 0;
                        else
                                Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->numbering = 1;
                        
                        myQueue.push(Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k));
                }
        }

        while(!myQueue.empty())
        {
                //int cur_gate_id = myQueue.front();
                Node* cur_gate = myQueue.front();
                
                for(k = 0; k < cur_gate->inputSize(); k++){
                        for(int j = 0; j < cur_gate->getInput(k)->inputSize(); j++){
                                int flag = 0;
                                if(cur_gate->getInput(k)->getInput(j)->signature() == FLIPFLOP){
                                        cur_gate->getInput(k)->getInput(j)->numbering = cur_gate->numbering;
                                        vicinity_DFFs.insert(((FlipflopNode*)(cur_gate->getInput(k)->getInput(j)))->FF_index);
                                }
                                else{
                                        for(int l = 0; l < cur_gate->getInput(k)->getInput(j)->inputSize(); l++)
                                                if(cur_gate->getInput(k)->getInput(j)->getInput(l)->isKnown() == false)
                                                        flag = 1;
                                        
                                        int old_numbering = cur_gate->getInput(k)->getInput(j)->numbering;
                                        if(flag == 1)
                                                cur_gate->getInput(k)->getInput(j)->numbering = 
                                                        min(cur_gate->getInput(k)->getInput(j)->numbering, (cur_gate->numbering + 1));
                                        else
                                                cur_gate->getInput(k)->getInput(j)->numbering = 
                                                        min(cur_gate->getInput(k)->getInput(j)->numbering, cur_gate->numbering);
                                
                                        assert(cur_gate->getInput(k)->getInput(j)->numbering < 1000);
                                        if(old_numbering != cur_gate->getInput(k)->getInput(j)->numbering)
                                                myQueue.push(cur_gate->getInput(k)->getInput(j));
                                }
                        }
                }
                
                myQueue.pop();
        }
        
        int count = 0;
        int tot_length = 0;
        int longest_length = 0;
        set<int>::iterator it_vic, it_temp;
        for(it_vic = vicinity_DFFs.begin(); it_vic != vicinity_DFFs.end(); it_vic++)
                if(*it_vic == DFF_id)
                        break;
        
        if(it_vic != vicinity_DFFs.end())
                vicinity_DFFs.erase(it_vic);
        
        for(it_vic = vicinity_DFFs.begin(); it_vic != vicinity_DFFs.end(); it_vic++){
                assert(Ci->getFlipflop(*it_vic)->numbering < 1000);
                
                int temp_len;
                if(key == 0)
                        temp_len = findPathInfo(DFF_id, *it_vic, TM->R0_seq_res_len);
                else
                        temp_len = findPathInfo(DFF_id, *it_vic, TM->R1_seq_res_len);
                
                if(temp_len == -1){
                        it_temp = it_vic;
                        vicinity_DFFs.erase(it_temp);
                }
                else{
                        if(longest_length < temp_len)
                                longest_length = temp_len;
                        
                        tot_length += Ci->getFlipflop(*it_vic)->numbering;
                        count++;
                }
        }
        
        if(key == 0)
                TM->longest_path_length_0 = longest_length;
        else
                TM->longest_path_length_1 = longest_length;
        
        //assert(longest_length != 0);
        //cout << "ext_logic_level is " << ext_logic_level << endl; 
        for(it_vic = vicinity_DFFs.begin(); it_vic != vicinity_DFFs.end(); it_vic++){
                //if(Ci->getFlipflop(*it_vic)->numbering <= ext_logic_level){
                        if(key == 0){
                                if(1.0 - (double)(TM->R0_seq_res_len[*it_vic])/(double)longest_length > my_lambda)
                                        //if(1.0 - (double)(TM->R0_seq_res_len[*it_vic])/831.0 > my_lambda)
                                TM->R0_seq.insert(*it_vic);
                        }
                        else{
                                if(1.0 - (double)(TM->R1_seq_res_len[*it_vic])/(double)longest_length > my_lambda)
                                //if(1.0 - (double)(TM->R1_seq_res_len[*it_vic])/831.0 > my_lambda)
                                        TM->R1_seq.insert(*it_vic);
                        }
                        //}
        }
        
        return ((double) longest_length);

        //if(count != 0)
        //return ((double)tot_length / (double)count);
        //else
        //return 0.0;
}


void Simulate::findVicinityFlipflop(int DFF_id, vector<resVal> &R_seq_P, set<int> &R_seq, int dir){
        
        int k; queue<Node*> myQueue;//only contains gate ids
        
        for(k = 0; k<Ci->flipflopSize(); ++k){
                if(k != DFF_id){
                        ((Node*)Ci->getFlipflop(k))->traversed = 0;
                        ((Node*)Ci->getFlipflop(k))->numbering = 1000;
                }
                else{
                        ((Node*)Ci->getFlipflop(k))->traversed = 0;
                        ((Node*)Ci->getFlipflop(k))->numbering = 0;
                }                      
        }
                        
        for(k = 0; k<Ci->gateSize(); ++k) 
        {
                Ci->getGate(k)->traversed = 0;
                Ci->getGate(k)->numbering = 1000;
        }
        
        //initializing the stack
        if(dir == 0)//fanout cone
        {
                if(Ci->getFlipflop(DFF_id)->getOutput(0)->preset == false){
                        for(k = 0; k < Ci->getFlipflop(DFF_id)->getOutput(0)->outputSize(); k++){
                                if(Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->signature() == FLIPFLOP){
                                }
                                else
                                {
                                        if(Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->getOutput(0)->isKnown() == true)
                                                Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->numbering = 0;
                                        else
                                                Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->numbering = 1;
                                        
                                        myQueue.push(Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k));
                                        Ci->getFlipflop(DFF_id)->getOutput(0)->getOutput(k)->traversed = 1;
                                }
                        }
                }
        }
        else//fanin cone
        {
                if(Ci->getFlipflop(DFF_id)->getInput(1)->preset == false){
                        for(k = 0; k < Ci->getFlipflop(DFF_id)->getInput(1)->inputSize(); k++){
                                if(Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->signature() == FLIPFLOP){
                                }
                                else
                                {
                                        int flag = 0;
                                        for(int j = 0; j < Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->inputSize(); j++)
                                                if(Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->getInput(j)->isKnown() == false)
                                                        flag = 1;
                                        
                                        if(flag == 0)
                                                Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->numbering = 0;
                                        else
                                                Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->numbering = 1;
                                        
                                        
                                        myQueue.push(Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k));
                                        Ci->getFlipflop(DFF_id)->getInput(1)->getInput(k)->traversed = 1;
                                }
                        }
                }
        }
        
        vector<int> vicinity_DFFs;        
        //iterative numbering
        if(dir == 0)//fanout cone
        {
                while(!myQueue.empty())
                {
                        //int cur_gate_id = myQueue.front();
                        Node* cur_gate = myQueue.front();
                        if(cur_gate->traversed >= 2)
                        {
                                myQueue.pop();
                                continue;
                        }
                        
                        //cout << "current gate id is " << cur_gate_id << endl;
                        for(k = 0; k < cur_gate->getOutput(0)->outputSize(); k++){
                                
                                int flag = 0;
                                if(cur_gate->getOutput(0)->getOutput(k)->signature() == FLIPFLOP)
                                {
                                        vicinity_DFFs.push_back(((FlipflopNode*)(cur_gate->getOutput(0)->getOutput(k)))->FF_index);
                                }
                                else
                                {
                                        if(cur_gate->getOutput(0)->getOutput(k)->getOutput(0)->isKnown() == false)
                                                flag = 1;
                                        
                                        myQueue.push(cur_gate->getOutput(0)->getOutput(k));
                                }
                                
                                if(cur_gate->getOutput(0)->getOutput(k)->traversed == 0)
                                {
                                        if(flag == 1)
                                                cur_gate->getOutput(0)->getOutput(k)->numbering = cur_gate->numbering + 1;
                                        else
                                                cur_gate->getOutput(0)->getOutput(k)->numbering = cur_gate->numbering;
                                }
                                
                                if(cur_gate->getOutput(0)->getOutput(k)->traversed > 0)
                                {
                                        if(flag == 1)
                                                cur_gate->getOutput(0)->getOutput(k)->numbering = 
                                                        min(cur_gate->getOutput(0)->getOutput(k)->numbering, (cur_gate->numbering + 1));
                                        else
                                                cur_gate->getOutput(0)->getOutput(k)->numbering = 
                                                        min(cur_gate->getOutput(0)->getOutput(k)->numbering, cur_gate->numbering);
                                }        
                                
                                assert(cur_gate->numbering < 1000);
                                assert(cur_gate->getOutput(0)->getOutput(k)->numbering < 1000);
                        }
                        
                        cur_gate->traversed++;
                        myQueue.pop();
                }
        }
        else
        {
                while(!myQueue.empty())
                {
                        //int cur_gate_id = myQueue.front();
                        Node* cur_gate = myQueue.front();
                        if(cur_gate->traversed >= 2)
                        {
                                myQueue.pop();
                                continue;
                        }
                        
                        //cout<< "current gate id is " << cur_gate_id << endl;
                        for(k = 0; k < cur_gate->inputSize(); k++){
                                
                                int flag = 0;
                                if(cur_gate->getInput(k)->inputSize() != 0){
                                        
                                        if(cur_gate->getInput(k)->getInput(0)->signature() == FLIPFLOP)
                                        {
                                                assert(((FlipflopNode*)(cur_gate->getInput(k)->getInput(0)))->FF_index < Ci->flipflopSize());
                                                vicinity_DFFs.push_back(((FlipflopNode*)(cur_gate->getInput(k)->getInput(0)))->FF_index);
                                        }
                                        else
                                        {
                                                for(int j = 0; j < cur_gate->getInput(k)->getInput(0)->inputSize(); j++)
                                                        if(cur_gate->getInput(k)->getInput(0)->getInput(j)->isKnown() == false)
                                                                flag = 1;
                                                
                                                myQueue.push(cur_gate->getInput(k)->getInput(0));
                                        }
                                        
                                        if(cur_gate->getInput(k)->getInput(0)->traversed == 0)
                                        {
                                                if(flag == 1)
                                                        cur_gate->getInput(k)->getInput(0)->numbering = cur_gate->numbering + 1;
                                                else
                                                        cur_gate->getInput(k)->getInput(0)->numbering = cur_gate->numbering;        
                                        }
                                        
                                        if(cur_gate->getInput(k)->getInput(0)->traversed > 0)
                                        {
                                                if(flag == 1)
                                                        cur_gate->getInput(k)->getInput(0)->numbering = 
                                                                min(cur_gate->getInput(k)->getInput(0)->numbering, (cur_gate->numbering + 1));
                                                else
                                                        cur_gate->getInput(k)->getInput(0)->numbering = 
                                                                min(cur_gate->getInput(k)->getInput(0)->numbering, cur_gate->numbering);
                                        }        
                                }
                        }
                        
                        cur_gate->traversed++;
                        myQueue.pop();
                }
        }
        
        int count = 0;
        int tot_length = 0;
        cout << "DFF " << DFF_id << endl;
        
        for(k = 0; k < vicinity_DFFs.size(); k++){
                if(Ci->getFlipflop(vicinity_DFFs[k])->numbering <= ext_logic_level){            
                        if(vicinity_DFFs[k] != DFF_id && Ci->getFlipflop(vicinity_DFFs[k])->numbering != 0){
                                R_seq.insert(vicinity_DFFs[k]);
                                tot_length += Ci->getFlipflop(vicinity_DFFs[k])->numbering;
                                count++;
                        }
                }
        }
        
        double avg_tot_length;
        if(count > 0){
                avg_tot_length = (double)tot_length / (double)count;
                cout << "avg_tot_legnth is " << avg_tot_length << endl;
                tot_vic_length += avg_tot_length;
        }
        else
                EL++;
        
}


bool Equal_Sig(pair<string, int>& p1, pair<string, int>& p2){
        return (p1.first == p2.first);
}


void Simulate::resMapAnalysis(string filename){
        
        int i = 0, k;
        Value vals[]={Zero,One,Z,X};
        
        const int MAX_LINE_LENGTH  = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        
        map<int, vector<pair<string, int> > > myMap;
        //map<int, vector<string > > myMap;
        
        set<int> gatePanaroma;
        while( i < assign_file_id){
                
                vector<pair<string, int> > temp_vec;
                //vector< string > temp_vec;
                /*
                stringstream ss;
                ss << i;
                
                string tmp = filename;
                tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
                tmp += "map_analy_";
                tmp += ss.str();
                cout << "map analysis file name is " << tmp << endl;
                
                ofstream out(tmp.c_str());
                */
                string tmp1 = filename;
                tmp1.erase(tmp1.begin() + tmp1.find("bench"), tmp1.end());
                tmp1 += "assign";
                
                //real simualte part
                initSimulate(tmp1);
                
                char pin_name[50];
                int data;
        
                string tmp = filename;
                tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
                tmp += "assign";
        
                stringstream ss;
                ss << i;
                tmp += "_" + ss.str();
                
                cout << "filename is " << tmp << endl;
                ifstream in_assign(tmp.c_str());
                if(!in_assign.is_open()){
                        cout << "Open assign file failed!" << endl;
                        exit(1);
                }
        
                while(!in_assign.eof()){
                        in_assign.getline(line_buffer, MAX_LINE_LENGTH);
                        sscanf (line_buffer, "%s\t%d", pin_name, &data);
                        //s = strtok(line_buffer, "\t\n");
                        tmp = pin_name;
                        cout << "pin is " << tmp << endl;
                        for(k=0; k<Ci->signalSize(); ++k){
                                if(Ci->getSignal(k)->getName() == tmp){
                                        //s = strtok(NULL, " \t\n");
                                        cout << "value is " << data << endl;
                                        Ci->getSignal(k)->untouchible = true;
                                        Value v = (Value)(data);
                                        Ci->getSignal(k)->setVal(v);
                                        break;
                                }
                        }                
                }
                
                
                /*
                for(int l=0; l<Ci->signalSize(); ++l){
                        if(Ci->getSignal(l)->untouchible == false) //KEY!!!
                                if(Ci->getSignal(l)->getVal() != 2)
                                cout << Ci->getSignal(l)->getName() << endl;
                }
                cin.get();
                */
                //LoadDFFMap(filename, i);
                initSimulateHybrid();
                PreSimHybrid1Trace();
                
                for(k = 0; k < Ci->signalSize(); ++k){
                        if(Ci->getSignal(k)->isKnown()){
                                gatePanaroma.insert(k);
                                temp_vec.push_back(make_pair(Ci->getSignal(k)->getName(), Ci->getSignal(k)->getVal()));
                                //out << Ci->getSignal(k)->getName() << "\t" << Ci->getSignal(k)->getVal() << endl;
                        }
                }
                
                myMap.insert(make_pair(i, temp_vec));
                //myMap[i] = temp_vec;
                i++;
        }
        
#ifdef PLACEMENT_INFO
        
        int j;
        string tmp1 = filename;
        tmp1.erase(tmp1.begin() + tmp1.find("bench"), tmp1.end());
        tmp1 += "nodes";
        
        string tmp2 = filename;
        tmp2.erase(tmp2.begin() + tmp2.find("bench"), tmp2.end());
        tmp2 += "nets";
        
        vector<int> gatePana(gatePanaroma.begin(), gatePanaroma.end());
        cout << "Total number of gates is " << Ci->gateSize() + Ci->flipflopSize() << endl;
        cout << "Total number of signals is " << Ci->signalSize() << endl;
        cout << "gatePana's size is " << gatePana.size() << endl;
        
        const string prefix_node = "p";
        ofstream outNodes(tmp1.c_str());
        
        set<Node*> real_pins;
        for(i = 0; i < gatePana.size(); ){
                if(Ci->getSignal(gatePana[i])->inputSize() == 0){
                        //if(Ci->getSignal(i)->getInput(0)->signature() == INPUT){
                        gatePana.erase(gatePana.begin() + i);
                        continue;
                }
                
                real_pins.insert(Ci->getSignal(gatePana[i])->getInput(0));
                i++;
        }
        
        outNodes << "NumNodes : " << real_pins.size() << endl;
        //long pos = outNodes.tellp();
        outNodes << "NumTerminals : 0" << endl;
        outNodes << endl;
        
        for(i = 0; i < real_pins.size(); i++){
                stringstream ss;
                ss << i;
                string tmp3 = prefix_node + ss.str(); 
                outNodes << tmp3 << "\t8\t12\t" << endl;
        }
        
        cout << "Potential net num(Max) is " << gatePana.size() << endl;
        cout << "Total number of nodes is " << real_pins.size() << endl;
        //stringstream ss;
        //ss << gatePana.size();
        //outNodes.seekp(pos - 1, ios::beg);
        //outNodes.write(ss.str().c_str(), strlen(ss.str().c_str())+1);
        outNodes.close();
        
        ofstream outNets(tmp2.c_str());
        outNets <<  "NumNets : " << '\n';
        //pos = outNets.tellp();
        outNets << "NumPins : " << real_pins.size() << endl;
        //long pos2 = outNets.tellp(); //should be write first
        outNets << endl;
        
        long net_cnt = 0;
        set<Node*>::iterator it_set;
        const string prefix_net = "N";
        for(i = 0; i < gatePana.size(); i++){
                set<Node*> pins;
                set<Node*>::iterator it_pins;
                for(j = 0; j < gatePana.size() && j != i; j++){
                        for(k = 0; k < Ci->getSignal(gatePana[i])->outputSize(); k++){
                                if(Ci->getSignal(gatePana[i])->getOutput(k) == Ci->getSignal(gatePana[j])->getInput(0))
                                {
                                        pins.insert(Ci->getSignal(gatePana[j])->getInput(0));
                                        break;
                                }
                        }
                }
                
                if(pins.size() == 0)
                        continue;
                else{
                        stringstream ss;
                        ss << net_cnt;
                        outNets <<  "NumDegree : " << pins.size() + 1 << "\t" << prefix_net + ss.str() << endl;
                        
                        it_set = real_pins.find(Ci->getSignal(gatePana[i])->getInput(0));
                        assert(it_set != real_pins.end());
                        stringstream ss1;
                        ss1 << distance(real_pins.begin(), it_set);
                        outNets << prefix_node + ss1.str() << "\tI :\t0.000\t0.000" << endl;
                                
                        for(it_pins = pins.begin(); it_pins != pins.end(); it_pins++) {
                                it_set = real_pins.find(*it_pins);
                                assert(it_set != real_pins.end());
                                stringstream ss1;
                                ss1 << distance(real_pins.begin(), it_set);
                                outNets << prefix_node + ss1.str() << "\tI :\t0.000\t0.000" << endl;
                        }
                        net_cnt++;
                }
        }
        
        //stringstream ss1;
        //ss1 << net_cnt;
        //outNets.seekp(pos - 1, ios::beg);
        //outNets.write(ss1.str().c_str(), strlen(ss1.str().c_str())+1);
        outNets.close();
        
        //generate the color file
        int color[gatePana.size()];
        memset(color, 0, sizeof(int) * gatePana.size());
        
        vector<int>::iterator it_vec_;
        vector<pair<string, int> >::iterator it_vec, it_vec1;
        string tmp3 = filename;
        tmp3.erase(tmp3.begin() + tmp3.find("bench"), tmp3.end());
        tmp3 += "color_";
        for(i = 0; i < assign_file_id; i++){
                for(it_vec = myMap[i].begin(); it_vec != myMap[i].end(); it_vec++){
                        for(k=0; k < Ci->signalSize(); ++k){
                                if(Ci->getSignal(k)->getName() == (*it_vec).first)
                                        break;
                        }
                        if(k != Ci->signalSize()){
                                it_vec_ = find(gatePana.begin(), gatePana.end(), k);
                                if(it_vec_ == gatePana.end())
                                        continue;
                                //assert(it_vec_ != gatePana.end());
                                if((*it_vec).second == 0)
                                        color[distance(gatePana.begin(), it_vec_)] = 1;
                                else
                                        color[distance(gatePana.begin(), it_vec_)] = 2;
                        }
                }
                
                stringstream ss;
                ss << i;
                string tmp4 = tmp3 + ss.str();
                ofstream outColor(tmp4.c_str());
                for(j = 0; j < gatePana.size(); j++){
                        stringstream ss;
                        ss << j;
                        outColor << prefix_node + ss.str() << "\t" << color[j] << endl;
                }
                outColor.close();
        }
        
#else

        cout << myMap.size() << endl;
        //t1 is all same, t2 is only signal is the same, t3 is all are not same
        vector<string> commonGates, commonGates_;
        vector<pair<string, int> >::iterator it_vec, it_vec1;
        for(it_vec = myMap[0].begin(); it_vec != myMap[0].end(); it_vec++){
                //cout << (*it_vec).first << endl;
                int t1 = 0; int t2 = 0;
                for( i = 1; i < assign_file_id; i++){
                        for(it_vec1 = myMap[i].begin(); it_vec1 != myMap[i].end(); it_vec1++){
                                if((*it_vec1).first == (*it_vec).first){
                                                t1++;
                                                if((*it_vec1).second == (*it_vec).second)
                                                        t2++;
                                                break;
                                }
                        }
                }
                
                if(t1 == assign_file_id - 1)
                        commonGates.push_back((*it_vec).first);
                
                if(t2 == assign_file_id - 1)
                        commonGates_.push_back((*it_vec).first);
        }
        
        
        map<int, vector<pair<string, int> > > myMap_;
        myMap_ = myMap; //backup before deleting common items
        //delete the common part
        for( i = 0; i < assign_file_id; i++ ){
                for(it_vec1 = myMap[i].begin(); it_vec1 != myMap[i].end(); it_vec1++){
                        if(std::find(commonGates.begin(), commonGates.end(), (*it_vec1).first) != commonGates.end()){
                                myMap[i].erase(it_vec1);
                                it_vec1--;
                        }
                }
        }
        
        for( i = 0; i < assign_file_id; i++ ){
                for(it_vec1 = myMap_[i].begin(); it_vec1 != myMap_[i].end(); it_vec1++){
                        if(std::find(commonGates_.begin(), commonGates_.end(), (*it_vec1).first) != commonGates_.end()){
                                myMap_[i].erase(it_vec1);
                                it_vec1--;
                        }
                }
        }
        
        //grouping based on the first criteria, common portion of signals 
        int cnt_common;
        multimap<int, int> modeTogroup;
        const double grouping_threshold1 = 0.6;
        //const double grouping_threshold2 = 0.6;
        const double grouping_threshold2 = my_lambda;
        
        for( i = 0; i < assign_file_id; i++ ){
                for( k = i + 1; k < assign_file_id; k++ ){
                        cnt_common = 0;
                        //for(it_vec = myMap[i].begin(); it_vec != myMap[i].end(); it_vec++){
                        //for(it_vec1 = myMap[k].begin(); it_vec1 != myMap[k].end(); it_vec1++){
                        for(it_vec = myMap_[i].begin(); it_vec != myMap_[i].end(); it_vec++){
                                for(it_vec1 = myMap_[k].begin(); it_vec1 != myMap_[k].end(); it_vec1++){
                                        if((*it_vec).first == (*it_vec1).first){
                                                cnt_common++;
                                                break;
                                        }
                                }
                        }
                        
                        //if((double)cnt_common / (double)(max(myMap[i].size(), myMap[k].size())) > grouping_threshold1){
                        if((double)cnt_common / (double)(max(myMap_[i].size(), myMap_[k].size())) > grouping_threshold1){
                                modeTogroup.insert(make_pair(i, k));
                                modeTogroup.insert(make_pair(k, i));
                        }        
                }
        }

        //grouping based on second criteria, common portion of values
        int array[assign_file_id];
        memset(array, 0, sizeof(int) * assign_file_id);
        
        vector<set<int> > new_groups;
        multimap<int, pair<int, int> >sub_group;//map[new_group_id]
        
        set<int>::iterator it_set, it_set1, it_temp;
        multimap<int,int>::iterator it;
        multimap<int, pair<int, int> >::iterator it1;
        pair <multimap<int,int>::iterator, multimap<int,int>::iterator> ret;
        pair <multimap<int, pair<int, int> >::iterator, multimap<int, pair<int, int> >::iterator> ret1;

        for( i = 0; i < assign_file_id; i++ ){
                
                set<int> temp;
                ret = modeTogroup.equal_range(i);
                
                if(distance(ret.first, ret.second) == 0){//single
                        temp.insert(i);
                        array[i] = 1;
                        new_groups.push_back(temp);
                        continue;
                }
                else{
                        if(array[i] == 1)//included by other groups
                                continue;
                        
                        temp.insert(i);
                        array[i] = 1;
                        
                        for (it=ret.first; it!=ret.second; ++it){
                                temp.insert(it->second);
                                array[it->second] = 1;
                        }
                }
                
                for (it_set = temp.begin(); it_set != temp.end(); ++it_set){
                        it_temp = it_set; it_temp++;
                        for (it_set1 = it_temp; it_set1 != temp.end(); ++it_set1){
                                cnt_common = 0;
                                for(it_vec = myMap_[*it_set].begin(); it_vec != myMap_[*it_set].end(); it_vec++){
                                        for(it_vec1 = myMap_[*it_set1].begin(); it_vec1 != myMap_[*it_set1].end(); it_vec1++){
                                                if((*it_vec).first == (*it_vec1).first){
                                                        if((*it_vec).second == (*it_vec1).second)
                                                                cnt_common++;
                                                        break;
                                                }
                                        }
                                }
                                
                                if((double)cnt_common / (double)(max(myMap_[*it_set].size(), myMap_[*it_set1].size())) > grouping_threshold2)
                                        sub_group.insert(make_pair(new_groups.size(),  make_pair(*it_set, *it_set1)));
                        }
                }
                        
                new_groups.push_back(temp);
        }
        
        for( i = 0; i < new_groups.size(); i++){
                cout << "group " << i << " has the following modes: " << endl;
                for (it_set = new_groups[i].begin(); it_set != new_groups[i].end(); ++it_set)
                        cout << *it_set << "\t";
                cout << endl;
                
                if(sub_group.find(i) == sub_group.end())
                        cout << "It has no sub group" << endl;
                else{
                        ret1 = sub_group.equal_range(i);
                        int cnt = 0;
                        for (it1 = ret1.first; it1 != ret1.second; ++it1){
                                cout << "The sub_group " << cnt << " contains modes " 
                                     << it1->second.first << " and " << it1->second.second << endl;
                        }
                }
        }
        
        cout << "Unique gates in " << endl;
        for( i = 0; i < assign_file_id; i++ ){
                cout  << i << " contians: " << endl;
                for(it_vec1 = myMap_[i].begin(); it_vec1 != myMap_[i].end(); it_vec1++){
                        cout << (*it_vec1).first << "\t" << (*it_vec1).second << endl;
                }
        }
        
        cout << "Common gates are: " << endl;
        for(k = 0; k <  commonGates.size(); k++)
                cout << commonGates[k] << endl;

#endif        
        //out.close();
}


pair<double,double> Simulate::huerSelectBiasedProcess(const int trace_size, vector<TresMap*> &Mymap , vector<int> &selected_traces, const char* filename, const double lampda){
        
        int i, j, k;
        double weight, temp_weight;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> MR;
        assert(selected_traces.size() == 0);
        
        cout<<"file name is "<<filename<<endl;        
        ofstream report(filename);
        report<< Ci->flipflopSize() <<endl;
        
        struct timeval start1, finish1, finish2, finish3, finish4;
        gettimeofday(&start1, NULL);
        
        while(selected_traces.size() < trace_size)
        {
                MR.clear();
                weight = 0.0;
                
                for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                {
                        temp_weight =0.0;
                        for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                        {
                                temp_weight += (1.0 - lampda) * probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P0);
                                //temp_weight += (1.0 - lampda) * probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), 
                                //(1.0 - (double)((*it_map)->R0_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_0 + 0.0000001)) * (*it_map)->P0);
                        }
                        
                        //how to deal with criticality is still unknown
                        for(it_set = (*it_map)->R0_com.begin(); it_set != (*it_map)->R0_com.end(); it_set++){
                                temp_weight += lampda * probAdjustGate(Ci->getGate(*it_set), Ci->getGate(*it_set)->getOutput(0), (*it_map)->P0);
                        }

                        for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++){
                                temp_weight += (1.0 - lampda) * probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                                //temp_weight += (1.0 - lampda) * probAdjust(Ci->getFlipflop(*it_set)->getOutput(0), 
                                //(1.0 - (double)((*it_map)->R1_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_1 + 0.0000001)) * (*it_map)->P1);
                        }
                        
                        //how to deal with criticality is still unknown
                        for(it_set = (*it_map)->R1_com.begin(); it_set != (*it_map)->R1_com.end(); it_set++){
                                temp_weight += lampda * probAdjustGate(Ci->getGate(*it_set), Ci->getGate(*it_set)->getOutput(0), (*it_map)->P1);
                        }
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }

                        TmapRate myMR;
                        myMR.weight = temp_weight;
                        myMR.it_map = it_map;                
                        MR.push_back(myMR);
                }
                
                if(weight == 0.0)
                        break;
                
                std::sort(MR.begin(), MR.end(), TrateMapSort);
                
                double largest_weight = MR[0].weight;
                const double topK = 0.03;
                for(j = 0; j < MR.size(); j++)
                {
                        if(MR[j].weight < topK * largest_weight)
                                break;
                }
                
                assert(j != 0);
                for(j = 0; j < MR.size(); j++)
                        MR[j].weight = 0.0;
                //if(selected_traces.size() == 0)
                //j = 100;
                
                //if( selected_traces.size() > 0 && j > 0.05 *
                //Ci->flipflopSize() )
                if(j > 0.05 * Ci->flipflopSize())
                        j = 0.05 * Ci->flipflopSize();
                
                MR.resize(j);
                cout << "Top candidate size is " << j << endl;
                
                k = j;
                int pos = 0;
                const int tot_thread_num = j;                

                while(k > 0){
                        
                        int thread_num;
                        if(k >= THREAD_NUM_T)
                                thread_num = THREAD_NUM_T;
                        else
                                thread_num = k % THREAD_NUM_T;

                        pthread_t PTs[thread_num];
                        
                        //cout << "thread_num is " << thread_num << endl;
                        for(j = 0; j < thread_num; j++)
                        {
                                for(i=0; i < Ci->flipflopSize(); ++i)
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                                for(i=0; i < selected_traces.size(); ++i)
                                        Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                                //cout << "see" << (*(MR[j].it_map))->DFF_id << endl;
                                Ci->getFlipflop((*(MR[pos + j].it_map))->DFF_id)->getOutput(0)->setTraced(true,j);
                        }
                        
                        int seed_num = 0;
                        while(seed_num < 3)
                        {
                                if(selected_traces.size())
                                        initACCMultThread(thread_num, seed_num);
                                else
                                        initMultThread(thread_num);
                                
                                for(j = 0; j < thread_num; j++)
                                {
                                        myWorkarg* mwa= new myWorkarg;
                                        mwa->Tid = j;
                                        mwa->Sim = this;
                                        LoadInitDFFValue(seed_num, j);
                                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                                }
                        
                                for(j = 0; j < thread_num; j++)
                                {
                                        myRetarg* mra = new myRetarg;
                                        pthread_join(PTs[j], (void**) &mra);
                                        
                                        MR[pos + mra->Tid].weight += mra->VN;
                                        delete mra;
                                }
                        
                                seed_num++;
                        }
                        
                        k -= thread_num;
                        pos += thread_num;
                }
                
                assert(pos == tot_thread_num);
                std::sort(MR.begin(), MR.end(), TrateMapSort);
                
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop((*(MR[0].it_map))->DFF_id)->getOutput(0)->getName() << endl;
                
                cout<<"VN is "<< MR[0].weight / 3 <<endl;
                double cur_VN = MR[0].weight / 3;
                selected_traces.push_back((*(MR[0].it_map))->DFF_id);
               
                for(j = 0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                
                
                //generate ref values
                int seed_num = 0;
                while(seed_num < 3){
                        
                        initMultThread(1);
                        LoadInitDFFValue(seed_num,0);
                        MultCalVNWOLOCK(0);
                        
                        for(i = 0; i < Ci->signalSize(); ++i){
                                Ci->getSignal(i)->Mult_Val0_ref[seed_num] = Ci->getSignal(i)->Mult_Val0[0];
                                Ci->getSignal(i)->Mult_Val1_ref[seed_num] = Ci->getSignal(i)->Mult_Val1[0];
                        }
                        
                        seed_num++;
                        
#ifdef PLACEMENT_INFO
                        if(selected_traces.size() >= 30 && selected_traces.size() <= 32){
                                cout << "Itr: " << selected_traces.size() << endl;
                                int check_point = 37;
                                const int bit_num = 8 * sizeof(BIT_TYPE);
                                for(int i = 0; i < TRACE_DEPTH_NUM; i++){
                                        for(int j = 0; j < 8 * sizeof(BIT_TYPE); j++){
                                        
                                                if(i * TRACE_DEPTH_NUM + j != check_point)
                                                        continue;
                                                else if(i * TRACE_DEPTH_NUM + j > check_point)
                                                        break;
                                        
                                                for(int l = 0; l < Ci->signalSize(); ++l){
                                                        cout << Ci->getSignal(l)->getName() << "\t";
                                                
                                                        BIT_TYPE temp1 = Ci->getSignal(l)->Mult_Val0_ref[seed_num].bits[i];
                                                        BIT_TYPE temp2 = Ci->getSignal(l)->Mult_Val1_ref[seed_num].bits[i];
                                                
                                                        temp1 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                                                        temp1 >>= bit_num - 1 - j;
                                                
                                                        temp2 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                                                        temp2 >>= bit_num - 1 - j;
                                                
                                                        if(temp1 == temp2)
                                                                cout << temp1 << endl;
                                                        else
                                                                cout << "2" << endl;
                                                }
                                        }
                                }
                        }
                        
#endif
                }

                double restime = 0.0;
                for(j = 0; j<Ci->flipflopSize(); ++j)
                {
                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                        Ci->getFlipflop(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                for(j = 0; j<Ci->gateSize(); ++j)
                {
                        restime = Ci->getGate(j)->getOutput(0)->isMultKnown(0);
                        Ci->getGate(j)->getOutput(0)->Cur_P = restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                }
                
                it_map1 = MR[0].it_map;
                Mymap.erase(it_map1);
                
                if(selected_traces.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                              << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                if(selected_traces.size() == 16)
                {
                        gettimeofday(&finish2, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                              << ( finish2.tv_sec+(finish2.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                        
                        addIslands(selected_traces, cur_VN);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, cur_VN);
                
                if(selected_traces.size() == 32)
                {
                        gettimeofday(&finish3, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                            << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        report<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                              << ( finish3.tv_sec+(finish3.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        report<< selected_traces.size() << endl;
                        report<< "seleted signals are...." << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        report<<endl;
                        report<<"Final Visibility is "<< cur_VN <<endl;
                }
        }
        
        cout << "Does not select the required number of traces, greedy adding islands starts..." << endl;
        while(selected_traces.size() < trace_size)
                greedyAddIslands(selected_traces);
                
        gettimeofday(&finish4, NULL);            
        cout<< "total runtime for Simulation-Based trace selection when selecting " << selected_traces.size() << " traces is: "
            << ( finish4.tv_sec+(finish4.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
        for(j = 0; j < Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        cout<< "seleted signals' outputs names are...." << endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                report<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        
        return reportSRR_GRR();
}


pair<double, double> Simulate::biasedSelect(const int trace_size, const char* filename, const double lampda){
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<TresMap*> Mymap;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        map< string, TresMap* > RSmap;
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        ofstream report(tmp.c_str());
        report<<Ci->flipflopSize()<<endl;
        //assignRandomWeight(0.2 * Ci->flipflopSize());
        
        struct timeval start1, finish1, finish2, finish3;
        for(i = 0; i < Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
        
        string tmp1 = filename;
        tmp1.erase(tmp1.begin() + tmp1.find("bench"), tmp1.end());
        tmp1 += "assign";
        
        initSimulate(tmp);
        cout << "sim init value starts" << endl;
        //SimInitDFFValue(filename);
        LoadDFFMap(filename, assign_file_id);//make sure the weight file is read in. There
        //are two LoadDFFMap functions
        cout << "sim init value ends" << endl;
        gettimeofday(&start1, NULL);
        
        double temp_path_length;
        double longest_path_length = 0.0;
        double tot_EL = 0.0;
        tot_vic_length = 0.0;
        
        //finish collecting resMap
        vector<TresMap*> *Mymap_ = new vector<TresMap*>[1];
        readResMap(filename, Mymap_, false, 0);
        
        gettimeofday(&finish1, NULL);
        cout << "longest path length is " << longest_path_length << endl;
        //cout << "total avg length is " << tot_EL << endl;
        //cout << "Average flipflop distance is " << tot_EL / (Ci->flipflopSize()) << endl;
        //cin.get();
        
        //int avg_tot_vic_length;
        //avg_tot_vic_length = floor(tot_vic_length / (double)tot_EL);
        
        //cout << "Average length of the vic is " << avg_tot_vic_length << endl;
        cout << "the percentage of island flipflops is " << (double)islands.size() / (double)Ci->flipflopSize() << endl;
        //cin.get();
        
        ofstream out("see"); 
        swap(Mymap, Mymap_[0]);
        vector<TresMap*> Mymap_Ori(Mymap);
        set<int>::iterator it_RM;
        
        double avg_Rlist_length = 0.0;
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
                avg_Rlist_length += (*it_map)->R0_seq.size() + (*it_map)->R1_seq.size();
        avg_Rlist_length /= Mymap.size();
        cout << "average RL size is " << avg_Rlist_length << endl;
        //exit (0);
        /*
        for(it_map = Mymap.begin();it_map != Mymap.end();it_map++)
        {
                out<<"DFF # "<<(*it_map)->DFF_id<<"\t"<<"Name\t" << Ci->getFlipflop((*it_map)->DFF_id)->getOutput(0)->getName()<<"\t"
                   <<(*it_map)->P0<<"\t"<<(*it_map)->P1<<endl;                  
                out<<"When traced flipflop has value 0, restored DFF size is "<<(*it_map)->R0_seq.size()<<endl;
                for(it_RM = (*it_map)->R0_seq.begin(); it_RM != (*it_map)->R0_seq.end(); it_RM++)
                        out<<(*it_RM)<<"\t";
                out<<endl;
                
                out<<"When traced flipflop has value 1, restored DFF size is "<<(*it_map)->R1_seq.size()<<endl;
                for(it_RM = (*it_map)->R1_seq.begin(); it_RM != (*it_map)->R1_seq.end(); it_RM++)
                        out<<(*it_RM)<<"\t";
                out<<endl;                

                out<<"When traced flipflop has value 0, restored Critical gate size is "<<(*it_map)->R0_com.size()<<endl;
                for(it_RM = (*it_map)->R0_com.begin(); it_RM != (*it_map)->R0_com.end(); it_RM++)
                        out<<(*it_RM)<<"\t";
                out<<endl;
                
                out<<"When traced flipflop has value 1, restored Critical gate size is "<<(*it_map)->R1_com.size()<<endl;
                for(it_RM = (*it_map)->R1_com.begin(); it_RM != (*it_map)->R1_com.end(); it_RM++)
                        out<<(*it_RM)<<"\t";
                out<<endl;        
        }        
        
        //cin.get();
        out.close();
        */
        cout<< "total runtime spend on generating the reachibility list is " << trace_size << " is: "
            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        gettimeofday(&start1, NULL);
        
        std::pair<double, double> SRR_GRR;
        SRR_GRR = huerSelectBiasedProcess(trace_size, Mymap, selected_traces, tmp.c_str(), lampda);
        const double init_SRR = SRR_GRR.first;
        cout << "Initial SRR is " << init_SRR << "\t";
        cout << "Initial GRR is " << SRR_GRR.second << endl;
        
        swap(this->selectedTraces, selected_traces);//added on 06/25/13
        int try_time = 0;
        double lampda2;
        double lower_bound = 0.0;
        double upper_bound = 1.0;
        
        for(i = 0; i < try_time; i++)
        {
                cout << "Optimization Round " << i << endl;
                lampda2 = 0.5 * (upper_bound + lower_bound);
                cout << "Lampda value is " << lampda2 << endl;
                
                Mymap = Mymap_Ori;
                selected_traces.clear();
                SRR_GRR = huerSelectBiasedProcess(trace_size, Mymap, selected_traces, tmp.c_str(), lampda2);
                
                if(SRR_GRR.first > 0.9 * init_SRR) //currently use 0.9 as the threshold
                        lower_bound = lampda2;
                else
                        upper_bound = lampda2;
                
                cout << "SRR is " << SRR_GRR.first << "\t"; 
                cout << "GRR is " << SRR_GRR.second << endl;
        }
        
        cout << "After " << try_time << " iterations, the final SRR and GRR are:" << endl;
        cout << "SRR is " << SRR_GRR.first << "\t"; 
        cout << "GRR is " << SRR_GRR.second << endl; 
        
        gettimeofday(&finish2, NULL);
        
        return SRR_GRR;
}


pair<double, double> Simulate::multimodeRef2SelectProcess(const int trace_size,  vector<TresMap*> *Mymap , vector<int> &selected_traces, const char* filename){
        
        int i, j, k;
        double weight, temp_weight;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> *MR;
        MR = new vector<TmapRate>[assign_file_id];
        assert(selected_traces.size() == 0);
        
        cout << "file name is " << filename << endl;        
        string tmp = filename;
        tmp += "_report";
        ofstream report(tmp.c_str());
        report<< Ci->flipflopSize() <<endl;
        
        double t_weight_compute = 0.0; //parallelizable
        double t_pick_best = 0.0; //serial
        double t_add_islands = 0.0; //serial
        double t_update_RR = 0.0; //parallelizable
        struct timeval start1, finish1;
        gettimeofday(&start1, NULL);
        
        while(selected_traces.size() < trace_size)
        {
                struct timeval start2, start3, finish2, finish3;
                gettimeofday(&start2, NULL);                
                for(i = 0; i < assign_file_id; i++){
                        
                        MR[i].clear();
                        weight = 0.0;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++)
                        {
                                temp_weight =0.0;
                                for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                                {
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0),(*it_map)->P0);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R0_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_0 + 0.0000001)) * (*it_map)->P0);
                                }
                                
                                for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++){
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R1_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_1 + 0.0000001)) * (*it_map)->P1);
                                }
                                
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                                
                                TmapRate myMR;
                                myMR.weight = temp_weight;
                                myMR.it_map = it_map;
                                myMR.DFF_id = (*it_map)->DFF_id;
                                MR[i].push_back(myMR);
                        }
                        
                        if(weight == 0.0)
                                break;
                
                        std::sort(MR[i].begin(), MR[i].end(), TrateMapSort);        
                }
                
                gettimeofday(&finish2, NULL);
                t_weight_compute += (double)(finish2.tv_sec+(finish2.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start3, NULL);
                
                set<int> common;
                set<int>::iterator it_set;

                for(j = 0; j < MR[0].size(); j++){
                        for(k = 0; k < MR[1].size(); k++){
                                if(MR[0][j].DFF_id == MR[1][k].DFF_id)
                                        common.insert(MR[0][j].DFF_id);
                        }
                }
                
                int *scores = new int[common.size()];
                memset(scores, 1, common.size()*sizeof(int));

                int cnt = 0;
                for(it_set = common.begin(); it_set != common.end(); it_set++){
                        for(i = 2; i < assign_file_id; i++){
                                for(j = 0; j < MR[i].size(); j++){
                                        if(MR[i][j].DFF_id == *it_set){
                                                scores[cnt]++;
                                                break;
                                        }
                                }
                        }
                        cnt++;
                }

                bool found = false;
                for(j = assign_file_id - 1; j > 1; j++){
                        for(i = 0; i < common.size(); i++){
                                if(scores[i] == j){
                                        found = true;
                                        break;
                                }
                        }
                        if(found == true)
                                break;
                }
                
                int best_cand;
                if(found == true){
                        it_set = common.begin();
                        for(k = 0; k < i; k++)
                                it_set++;

                        best_cand = *it_set;
                        cout<<"Chosen flipflop's name in this round is "<<
                                Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                }
                else{
                        cout << "not found using new way!" << endl;
                        //cin.get();
                        
                        vector<TmapRate> MR_;
                        for(i = 0; i < assign_file_id; i++){
                                TmapRate myMR;
                                myMR.DFF_id = MR[i][0].DFF_id;
                                myMR.weight = 0.0;
                                MR_.push_back(myMR);
                        }
                        
                        for(int l = 0; l < assign_file_id; l++){
                                
                                k = MR_.size();
                                int pos = 0;
                                const int tot_thread_num = k;
                                
                                initSimulate(filename);
                                LoadDFFMap(filename, l);
                                
                                while(k > 0){
                                        
                                        int thread_num;
                                        if(k >= THREAD_NUM_T)
                                                thread_num = THREAD_NUM_T;
                                        else
                                                thread_num = k % THREAD_NUM_T;

                                        pthread_t PTs[thread_num];
                                        //cout << "thread_num is " << thread_num << endl;
                                        for(j = 0; j < thread_num; j++)
                                        {
                                                for(i=0; i < Ci->flipflopSize(); ++i)
                                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                                                
                                                for(i=0; i < selected_traces.size(); ++i)
                                                        Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);

                                                //cout << "see" << (*(MR[j].it_map))->DFF_id << endl;
                                                Ci->getFlipflop(MR_[pos + j].DFF_id)->getOutput(0)->setTraced(true,j);
                                        }

                                        int seed_num = 0;
                                        while(seed_num < 3)
                                        {
                                                initMultThread(thread_num);
                                                
                                                for(j = 0; j < thread_num; j++)
                                                {
                                                        myWorkarg* mwa= new myWorkarg;
                                                        mwa->Tid = j;
                                                        mwa->Sim = this;
                                                        LoadInitDFFValue(seed_num, j);
                                                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                                                }
                                        
                                                for(j = 0; j < thread_num; j++)
                                                {
                                                        myRetarg* mra = new myRetarg;
                                                        pthread_join(PTs[j], (void**) &mra);

                                                        MR_[pos + mra->Tid].weight += mra->VN;
                                                        delete mra;
                                                }

                                                seed_num++;
                                        }
                                        
                                        k -= thread_num;
                                        pos += thread_num;
                                }
                        }
                        
                        //assert(pos == tot_thread_num);
                        //cout << "MR_ size is " << MR_.size() << endl;
                        best_cand = MR_[0].DFF_id;
                        if(MR_.size() == 2)
                        {
                                if(MR_[1].weight > MR_[0].weight)
                                        best_cand = MR_[1].DFF_id;
                        }
                        else{
                                std::sort(MR_.begin(), MR_.end(), TrateMapSort);
                                best_cand = MR_[0].DFF_id;
                        }
                        
                        cout << "Chosen flipflop's name in this round is " << Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                }
                
                
                gettimeofday(&finish3, NULL);
                t_pick_best += (double)(finish3.tv_sec+(finish3.tv_usec/1000000.0) - start3.tv_sec+(start3.tv_usec/1000000.0));
                
                gettimeofday(&start2, NULL);
                assert(best_cand != -1);
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                
                selected_traces.push_back(best_cand);
                
                for(j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);

                //generate ref values
                double VN_bar = 0.0;
                for( i = 0; i < assign_file_id; i++){
                        
                        initSimulate(filename);
                        LoadDFFMap(filename, i);
                        
                        int seed_num = 0;
                        double cur_VN = 0.0;
                
                        while(seed_num < 3){
                                
                                initMultThread(1);
                                LoadInitDFFValue(seed_num,0);
                                cur_VN += MultCalVNWOLOCK(0);
                                
                                double restime = 0.0;
                                for(j=0; j<Ci->flipflopSize(); ++j)
                                {
                                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                                        Ci->getFlipflop(j)->getOutput(0)->RR_array[i] += restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                                }
                                
                                seed_num++;
                        }
                
                        for(j=0; j<Ci->flipflopSize(); ++j)
                                Ci->getFlipflop(j)->getOutput(0)->RR_array[i] /= 3;
                        
                        cout << "VN for mode " << i << " is "<< cur_VN / 3 <<endl;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++){
                                if((*it_map)->DFF_id == best_cand){
                                        Mymap[i].erase(it_map);
                                        break;
                                }
                        }
                        
                        if(i == 0)
                                VN_bar = cur_VN / 3;
                }
                
                gettimeofday(&finish2, NULL);
                t_update_RR += (double)(finish2.tv_sec+(finish2.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start3, NULL);
                if(selected_traces.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        addIslands(selected_traces, VN_bar);
                }
                
                if(selected_traces.size() == 16)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        addIslands(selected_traces, VN_bar);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, VN_bar);
                
                if(selected_traces.size() == 32)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;        
                }
                
                gettimeofday(&finish3, NULL);
                t_add_islands += (double)(finish3.tv_sec+(finish3.tv_usec/1000000.0) - start3.tv_sec+(start3.tv_usec/1000000.0));
        }
        
        gettimeofday(&finish1, NULL);
        
        cout<< "total runtime for Simulation-Based trace selection when selecting " << trace_size << " is " 
            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //t_pick_best serial
        t_weight_compute /= assign_file_id; //parallelizable
        t_update_RR /= assign_file_id; //parallelizable
        cout << "After parallelization, ideal time for weight computation is " << t_weight_compute << endl;
        cout << "Pick best time is " << t_pick_best << endl;
        cout << "Add islands time is " << t_add_islands << endl;
        cout << "After parallelization, ideal time for update RR is " << t_update_RR << endl;

        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        cout<< "seleted signals' outputs names are...." << endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        
        return reportSRR_GRR();
}


pair<double, double> Simulate::multimodeRef2Select(const int trace_size, const char* filename){
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<TresMap*> *Mymap;
        Mymap = new vector<TresMap*>[assign_file_id];

        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        for(i = 0; i < Ci->signalSize(); ++i) {
                Ci->getSignal(i)->P0_array = new float[assign_file_id];
                Ci->getSignal(i)->P1_array = new float[assign_file_id];
                Ci->getSignal(i)->RR_array = new double[assign_file_id];
        }
        
        double RL_gen_time = 0.0;
        struct timeval start1, finish1, finish2, finish3;
        
        gettimeofday(&start1, NULL);
        readResMap(filename, Mymap, true, -1);
        gettimeofday(&finish1, NULL);       
        cout<< "total runtime for generating reachability list for different modes is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        RL_gen_time = (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) / assign_file_id;
        cout << "After parallelization, the ideal runtime for RL gen is " << RL_gen_time << endl;
        //---------------------------------------Min------------------------------------------------------
        set<int>::iterator it_RM;
        
        std::pair<double, double> SRR_GRR;
        SRR_GRR = multimodeRef2SelectProcess(trace_size,  Mymap, selected_traces, &filename[0]);
        
        const double init_SRR = SRR_GRR.first;
        cout << "Initial SRR is " << init_SRR << "\t";
        cout << "Initial GRR is " << SRR_GRR.second << endl;
        
        return SRR_GRR;
}                


pair<double, double> Simulate::multimodeSelectProcess(const int trace_size,  vector<TresMap*> *Mymap , vector<int> &selected_traces, const char* filename){
        
        int i, j, k;
        double weight, temp_weight;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> *MR;
        MR = new vector<TmapRate>[assign_file_id];
        assert(selected_traces.size() == 0);
        
        cout << "file name is " << filename << endl;        
        string tmp = filename;
        tmp += "_report";
        ofstream report(tmp.c_str());
        report<< Ci->flipflopSize() <<endl;
        
        double t_weight_compute = 0.0; //parallelizable
        double t_pick_best = 0.0; //serial
        double t_add_islands = 0.0; //serial
        double t_update_RR = 0.0; //parallelizable
        struct timeval start1, finish1;
        gettimeofday(&start1, NULL);
        
        while(selected_traces.size() < trace_size)
        {
                struct timeval start2, start3, finish2, finish3;
                gettimeofday(&start2, NULL);                
                for(i = 0; i < assign_file_id; i++){
                        
                        MR[i].clear();
                        weight = 0.0;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++)
                        {
                                temp_weight =0.0;
                                for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                                {
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0),(*it_map)->P0);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R0_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_0 + 0.0000001)) * (*it_map)->P0);
                                }
                                
                                for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++){
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R1_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_1 + 0.0000001)) * (*it_map)->P1);
                                }
                                
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                                
                                TmapRate myMR;
                                myMR.weight = temp_weight;
                                myMR.it_map = it_map;
                                myMR.DFF_id = (*it_map)->DFF_id;
                                MR[i].push_back(myMR);
                        }
                        
                        if(weight == 0.0)
                                break;
                
                        std::sort(MR[i].begin(), MR[i].end(), TrateMapSort);        
                }
                
                gettimeofday(&finish2, NULL);
                t_weight_compute += (double)(finish2.tv_sec+(finish2.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start3, NULL);
                vector<TmapRate> MR_t;
                TmapRate myMR;
                
                float *scores = new float[Ci->flipflopSize()]; 
                memset(scores, 0.0, Ci->flipflopSize()*sizeof(float));
                
                for(i = 0; i < assign_file_id; i++)
                        for(j = 0; j < MR[i].size(); j++)
                                scores[MR[i][j].DFF_id] += MR[i][j].weight;
                
                for(i = 0; i < Ci->flipflopSize(); i++)
                {
                        myMR.weight = scores[i];
                        myMR.it_map = it_map;
                        myMR.DFF_id = i;
                        MR_t.push_back(myMR);
                }
                std::sort(MR_t.begin(), MR_t.end(), TrateMapSort);        
                
                //uniform sampling
                const double topK = 0.03;
                MR_t.resize(floor(MR_t.size() * topK));
                for(j = 0; j < MR_t.size(); j++)
                        MR_t[j].weight = 0.0;
                
                assert(j != 0);
                cout << "Top candidate size is " << MR_t.size() << endl;
                
                for(int l = 0; l < assign_file_id; l++){
                        
                        initSimulate(filename);
                        LoadDFFMap(filename, l);
                        
                        k = MR_t.size();
                        int pos = 0;
                        const int tot_thread_num = MR_t.size();
                
                        while(k > 0){
                        
                                int thread_num;
                                if(k >= THREAD_NUM_T)
                                        thread_num = THREAD_NUM_T;
                                else
                                        thread_num = k % THREAD_NUM_T;
                        
                                pthread_t PTs[thread_num];
                        
                                //cout << "thread_num is " << thread_num << endl;
                                for(j = 0; j < thread_num; j++)
                                {
                                        for(i=0; i < Ci->flipflopSize(); ++i)
                                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                                
                                        for(i=0; i < selected_traces.size(); ++i)
                                                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                                        //cout << "see" << (*(MR[j].it_map))->DFF_id << endl;
                                        Ci->getFlipflop(MR_t[pos + j].DFF_id)->getOutput(0)->setTraced(true,j);
                                }
                        
                                int seed_num = 0;
                                while(seed_num < 3)
                                {
                                        if(selected_traces.size())
                                                initACCMultThread_MM(thread_num, seed_num, l);
                                        else
                                                initMultThread(thread_num);
                                        
                                        for(j = 0; j < thread_num; j++)
                                        {
                                                myWorkarg* mwa= new myWorkarg;
                                                mwa->Tid = j;
                                                mwa->Sim = this;
                                                LoadInitDFFValue(seed_num, j);
                                                pthread_create(&PTs[j], NULL, work, (void*)mwa);
                                        }
                        
                                        for(j = 0; j < thread_num; j++)
                                        {
                                                myRetarg* mra = new myRetarg;
                                                pthread_join(PTs[j], (void**) &mra);
                                                
                                                MR_t[pos + mra->Tid].weight += mra->VN;
                                                delete mra;
                                        }
                                        
                                        seed_num++;        
                                }
                                
                                k -= thread_num;
                                pos += thread_num;
                        }
                        assert(pos == tot_thread_num);
                }
                
                std::sort(MR_t.begin(), MR_t.end(), TrateMapSort);
                
                int best_cand = MR_t[0].DFF_id;
                
                gettimeofday(&finish3, NULL);
                t_pick_best += (double)(finish3.tv_sec+(finish3.tv_usec/1000000.0) - start3.tv_sec+(start3.tv_usec/1000000.0));
                
                gettimeofday(&start2, NULL);
                assert(best_cand != -1);
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                
                selected_traces.push_back(best_cand);
                
                for(j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);

                //generate ref values
                double VN_bar = 0.0;
                for( i = 0; i < assign_file_id; i++){
                        
                        initSimulate(filename);
                        LoadDFFMap(filename, i);
                        
                        int seed_num = 0;
                        double cur_VN = 0.0;
                        
                        while(seed_num < 3){
                                
                                initMultThread(1);
                                LoadInitDFFValue(seed_num,0);
                                cur_VN += MultCalVNWOLOCK(0);
                                
                                for(j = 0; j < Ci->signalSize(); ++j){
                                        Ci->getSignal(j)->Mult_Val0_ref_MM[seed_num][i] = Ci->getSignal(j)->Mult_Val0[0];
                                        Ci->getSignal(j)->Mult_Val1_ref_MM[seed_num][i] = Ci->getSignal(j)->Mult_Val1[0];
                                }
                                
                                double restime = 0.0;
                                for(j=0; j<Ci->flipflopSize(); ++j)
                                {
                                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                                        Ci->getFlipflop(j)->getOutput(0)->RR_array[i] += restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                                }
                                
                                seed_num++;
                        }
                        
                        for(j=0; j<Ci->flipflopSize(); ++j)
                                Ci->getFlipflop(j)->getOutput(0)->RR_array[i] /= 3;
                        
                        cout << "VN for mode " << i << " is "<< cur_VN / 3 <<endl;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++){
                                if((*it_map)->DFF_id == best_cand){
                                        Mymap[i].erase(it_map);
                                        break;
                                }
                        }
                        
                        if(i == 0)
                                VN_bar = cur_VN / 3;
                }
                
                gettimeofday(&finish2, NULL);
                t_update_RR += (double)(finish2.tv_sec+(finish2.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start3, NULL);
                if(selected_traces.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        addIslands(selected_traces, VN_bar);
                }
                
                if(selected_traces.size() == 16)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        addIslands(selected_traces, VN_bar);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, VN_bar);
                
                if(selected_traces.size() == 32)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;        
                }
                
                gettimeofday(&finish3, NULL);
                t_add_islands += (double)(finish3.tv_sec+(finish3.tv_usec/1000000.0) - start3.tv_sec+(start3.tv_usec/1000000.0));
        }
        
        gettimeofday(&finish1, NULL);
        
        cout<< "total runtime for Simulation-Based trace selection when selecting " << trace_size << " is " 
            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //t_pick_best serial
        t_weight_compute /= assign_file_id; //parallelizable
        t_update_RR /= assign_file_id; //parallelizable
        cout << "After parallelization, ideal time for weight computation is " << t_weight_compute << endl;
        cout << "Pick best time is " << t_pick_best << endl;
        cout << "Add islands time is " << t_add_islands << endl;
        cout << "After parallelization, ideal time for update RR is " << t_update_RR << endl;

        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        cout<< "seleted signals' outputs names are...." << endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        
        return reportSRR_GRR();
}


pair<double, double> Simulate::multimodeSelect(const int trace_size, const char* filename){
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<TresMap*> *Mymap;
        Mymap = new vector<TresMap*>[assign_file_id];

        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        for(i = 0; i < Ci->signalSize(); ++i) {
                Ci->getSignal(i)->P0_array = new float[assign_file_id];
                Ci->getSignal(i)->P1_array = new float[assign_file_id];
                Ci->getSignal(i)->RR_array = new double[assign_file_id];
        }
        
        double RL_gen_time = 0.0;
        struct timeval start1, finish1, finish2, finish3;
        
        gettimeofday(&start1, NULL);
        readResMap(filename, Mymap, true, -1);
        gettimeofday(&finish1, NULL);       
        cout<< "total runtime for generating reachability list for different modes is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        RL_gen_time = (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) / assign_file_id;
        cout << "After parallelization, the ideal runtime for RL gen is " << RL_gen_time << endl;
        //---------------------------------------Min------------------------------------------------------
        set<int>::iterator it_RM;
        
        std::pair<double, double> SRR_GRR;
        SRR_GRR = multimodeSelectProcess(trace_size,  Mymap, selected_traces, &filename[0]);
        
        const double init_SRR = SRR_GRR.first;
        cout << "Initial SRR is " << init_SRR << "\t";
        cout << "Initial GRR is " << SRR_GRR.second << endl;
        
        return SRR_GRR;
}


pair<double, double> Simulate::multimodeMergeSelectProcess(const int trace_size,  vector<TresMap*> *Mymap , vector<int> &selected_traces, vector<int> &modes, const char* filename){
        
        int i, j, k;
        double weight, temp_weight;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> *MR;
        MR = new vector<TmapRate>[modes.size()];
        assert(selected_traces.size() == 0);
        
        cout << "file name is " << filename << endl;        
        string tmp = filename;
        tmp += "_report";
        ofstream report(tmp.c_str());
        report<< Ci->flipflopSize() <<endl;
        
        double t_weight_compute = 0.0; //parallelizable
        double t_pick_best = 0.0; //serial
        double t_add_islands = 0.0; //serial
        double t_update_RR = 0.0; //parallelizable
        struct timeval start1, finish1;
        gettimeofday(&start1, NULL);
        
        while(selected_traces.size() < trace_size)
        {
                struct timeval start2, start3, finish2, finish3;
                gettimeofday(&start2, NULL);                
                for(i = 0; i < modes.size(); i++){
                        
                        MR[i].clear();
                        weight = 0.0;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++)
                        {
                                temp_weight =0.0;
                                for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                                {
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0),(*it_map)->P0);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R0_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_0 + 0.0000001)) * (*it_map)->P0);
                                }
                                
                                for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++){
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R1_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_1 + 0.0000001)) * (*it_map)->P1);
                                }
                                
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                                
                                TmapRate myMR;
                                myMR.weight = temp_weight;
                                myMR.it_map = it_map;
                                myMR.DFF_id = (*it_map)->DFF_id;
                                MR[i].push_back(myMR);
                        }
                        
                        if(weight == 0.0)
                                break;
                
                        std::sort(MR[i].begin(), MR[i].end(), TrateMapSort);        
                }
                
                gettimeofday(&finish2, NULL);
                t_weight_compute += (double)(finish2.tv_sec+(finish2.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start3, NULL);                
                float *scores = new float[Ci->flipflopSize()]; 
                memset(scores, 0.0, Ci->flipflopSize()*sizeof(float));
                
                for(i = 0; i < modes.size(); i++)
                        for(j = 0; j < MR[i].size(); j++)
                                scores[MR[i][j].DFF_id] += MR[i][j].weight;
                
                int best_cand = -1;
                double bar = 0.0;
                for(i = 0; i < Ci->flipflopSize(); i++)
                {
                        if(scores[i] > bar){
                                bar = scores[i];
                                best_cand = i;
                        }
                }
                
                gettimeofday(&finish3, NULL);
                t_pick_best += (double)(finish3.tv_sec+(finish3.tv_usec/1000000.0) - start3.tv_sec+(start3.tv_usec/1000000.0));
                
                gettimeofday(&start2, NULL);
                assert(best_cand != -1);
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                
                selected_traces.push_back(best_cand);
                
                for(j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);

                //generate ref values
                double VN_bar = 0.0;
                for( i = 0; i < modes.size(); i++){
                        
                        initSimulate(filename);
                        LoadDFFMap(filename, modes[i]);
                        
                        int seed_num = 0;
                        double cur_VN = 0.0;
                
                        while(seed_num < 3){
                                
                                initMultThread(1);
                                LoadInitDFFValue(seed_num,0);
                                cur_VN += MultCalVNWOLOCK(0);
                                
                                double restime = 0.0;
                                for(j=0; j<Ci->flipflopSize(); ++j)
                                {
                                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                                        Ci->getFlipflop(j)->getOutput(0)->RR_array[i] += restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                                }
                                
                                seed_num++;
                        }
                
                        for(j=0; j<Ci->flipflopSize(); ++j)
                                Ci->getFlipflop(j)->getOutput(0)->RR_array[i] /= 3;
                        
                        cout << "VN for mode " << i << " is "<< cur_VN / 3 <<endl;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++){
                                if((*it_map)->DFF_id == best_cand){
                                        Mymap[i].erase(it_map);
                                        break;
                                }
                        }
                        
                        if(i == 0)
                                VN_bar = cur_VN / 3;
                }
                
                gettimeofday(&finish2, NULL);
                t_update_RR += (double)(finish2.tv_sec+(finish2.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start3, NULL);
                if(selected_traces.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        addIslands(selected_traces, VN_bar);
                }
                
                if(selected_traces.size() == 16)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        addIslands(selected_traces, VN_bar);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, VN_bar);
                
                if(selected_traces.size() == 32)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;        
                }
                
                gettimeofday(&finish3, NULL);
                t_add_islands += (double)(finish3.tv_sec+(finish3.tv_usec/1000000.0) - start3.tv_sec+(start3.tv_usec/1000000.0));
        }
        
        gettimeofday(&finish1, NULL);
        
        cout<< "total runtime for Simulation-Based trace selection when selecting " << trace_size << " is " 
            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //t_pick_best serial
        t_weight_compute /= modes.size(); //parallelizable
        t_update_RR /= modes.size(); //parallelizable
        cout << "After parallelization, ideal time for weight computation is " << t_weight_compute << endl;
        cout << "Pick best time is " << t_pick_best << endl;
        cout << "Add islands time is " << t_add_islands << endl;
        cout << "After parallelization, ideal time for update RR is " << t_update_RR << endl;
        
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "trace_check_ILP0";
        ofstream out(str.c_str());
        out << selected_traces.size() << endl;
        for(i = 0; i < selected_traces.size(); i++){
                cout << Ci->getFlipflop(selected_traces[i])->getOutput(0)->getName() << endl;
                out << Ci->getFlipflop(selected_traces[i])->getOutput(0)->getName() << endl;
        }
        out << "!" << endl;
        out << "&&&";
        out.close();
        
        cout << "Input the total number of modes: ";
        int total_mode_num;
        cin >> total_mode_num;
        std::pair<double, double> SRR_GRR;
        for(i = 0; i < total_mode_num; i++){
                assign_file_id = i;
                SRR_GRR = Check_Traces_SRR_GRR(filename);
                cout << "SRR is " << SRR_GRR.first << endl;
        }
        
        return make_pair(0.0, 0.0);
}


pair<double, double> Simulate::multimodeMergeSelect(const int trace_size, const char* filename){
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        cout << "Input the modes considered for selection" << endl;
        
        int mode;
        vector<int> modes;
        
        if(tmp.find("DMA") != string::npos){
                modes.push_back(0);
                modes.push_back(4);
                modes.push_back(5);
                modes.push_back(7);
        }
        else{
                while(1){
                        cout << "Give a mode" << endl;
                        cin >> mode;
                        if(mode == -1)
                                break;
                        modes.push_back(mode);
                }
        }
        
        for(i = 0; i < Ci->signalSize(); ++i) {
                Ci->getSignal(i)->P0_array = new float[modes.size()];
                Ci->getSignal(i)->P1_array = new float[modes.size()];
                Ci->getSignal(i)->RR_array = new double[modes.size()];
        }
        
        vector<TresMap*> *Mymap;
        Mymap = new vector<TresMap*>[modes.size()];
        
        double RL_gen_time = 0.0;
        struct timeval start1, finish1, finish2, finish3;
        
        gettimeofday(&start1, NULL);
        for(i = 0; i < modes.size(); i++){
                assign_file_id = modes[i];
                readResMap(filename, Mymap, false, i);
        }
        gettimeofday(&finish1, NULL);       
        cout<< "total runtime for generating reachability list for different modes is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        RL_gen_time = (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) / assign_file_id;
        cout << "After parallelization, the ideal runtime for RL gen is " << RL_gen_time << endl;
        //---------------------------------------Min------------------------------------------------------
        set<int>::iterator it_RM;
        
        std::pair<double, double> SRR_GRR;
        SRR_GRR = multimodeMergeSelectProcess(trace_size,  Mymap, selected_traces, modes, &filename[0]);
        
        const double init_SRR = SRR_GRR.first;
        cout << "Initial SRR is " << init_SRR << "\t";
        cout << "Initial GRR is " << SRR_GRR.second << endl;
        
        return SRR_GRR;
}


void Simulate::readResMap(const char* filename, vector<TresMap*> *Mymap, bool batch, int idx){
        
        const int MAX_LINE_LENGTH = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        
        if(batch == true){
                
                string tmp = filename;
                tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
                tmp += "resmap";
                string tmp_bck = tmp;
                
                set<int>::iterator it_RM;
                for(int i = 0; i < assign_file_id; i++){
                        
                        tmp = tmp_bck;
                        stringstream ss;
                        ss << i;
                        tmp += "_" + ss.str();
                        ifstream fin(tmp.c_str());
                        cout << "Reading resmap of mode " << i << endl;
                        //cin.get();
                        
                        while(!fin.eof()){
                                fin.getline(line_buffer, MAX_LINE_LENGTH);
                                TresMap* myMap_ = new TresMap[1];
                                char *s = strtok(line_buffer, "\t\n");
                                if(s == NULL)
                                        break;
                        
                                myMap_->DFF_id = atoi(s);
                                s = strtok(NULL, " \t\n");
                                myMap_->P0 = atof(s);
                                s = strtok(NULL, " \t\n");
                                myMap_->P1 = atof(s);
                                s = strtok(NULL, " \t\n");
                                myMap_->longest_path_length_0 = atoi(s);
                                s = strtok(NULL, " \t\n");
                                myMap_->longest_path_length_1 = atoi(s);
                                
                                //cout << myMap_->DFF_id << endl;
                                //cout << myMap_->P0 << endl;
                                //cout << myMap_->P1 << endl;
                                
                                int temp, key;
                                fin.getline(line_buffer, MAX_LINE_LENGTH);
                                s = strtok(line_buffer, "\t\n");
                                if(s != NULL){
                                        bool even = true;
                                        temp = atoi(s);
                                        myMap_->R0_seq.insert(temp);
                                        key = temp;
                                        //cout << temp << "\t";
                                        while(1){
                                                s = strtok(NULL, " \t\n");
                                                if(s == NULL)
                                                        break;
                                                
                                                if(even == true){
                                                        temp = atoi(s);
                                                        myMap_->R0_seq_res_len[key] = temp;
                                                }
                                                else{
                                                        temp = atoi(s);
                                                        myMap_->R0_seq.insert(temp);
                                                        key = temp;
                                                }
                                                
                                                even = !even;
                                                //cout << temp << "\t";
                                        }
                                        //cout << endl;
                                }
                                
                                fin.getline(line_buffer, MAX_LINE_LENGTH);
                                s = strtok(line_buffer, "\t\n");
                                if(s == NULL)
                                        continue;
                                
                                temp = atoi(s);
                                myMap_->R1_seq.insert(temp);
                                key = temp;
                                bool even = true;
                                //cout << temp << "\t";
                                while(1){
                                        s = strtok(NULL, " \t\n");
                                        if(s == NULL)
                                                break;
                                        
                                        if(even == true){
                                                temp = atoi(s);
                                                myMap_->R1_seq_res_len[key] = temp;
                                        }
                                        else{
                                                temp = atoi(s);
                                                key = temp;
                                                myMap_->R1_seq.insert(temp);
                                        }
                                        
                                        even = !even;
                                        //cout << temp << "\t";
                                }
                                //cout << endl;
                                
                                Mymap[i].push_back(myMap_);
                        }
                }
                
                for(int i = 0; i < assign_file_id; i++)
                        cout << "In mode " << i << ", island flipflop's percentage is " << 1.0 - ((double) Mymap[i].size() / (double) Ci->flipflopSize()) << endl;
        }
        else{
                string tmp = filename;
                tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
                tmp += "resmap";
                
                if(assign_file_id != -1){
                        stringstream ss;
                        ss << assign_file_id;
                        tmp += "_" + ss.str();
                }
                cout << "reading resmap " << tmp << endl;
                
                ifstream fin(tmp.c_str());
                while(!fin.eof())
                {
                        fin.getline(line_buffer, MAX_LINE_LENGTH);
                        TresMap* myMap_ = new TresMap[1];
                        char *s = strtok(line_buffer, "\t\n");
                        if(s == NULL)
                                break;
                        
                        myMap_->DFF_id = atoi(s);
                        s = strtok(NULL, " \t\n");
                        myMap_->P0 = atof(s);
                        s = strtok(NULL, " \t\n");
                        myMap_->P1 = atof(s);
                        s = strtok(NULL, " \t\n");
                        myMap_->longest_path_length_0 = atoi(s);
                        s = strtok(NULL, " \t\n");
                        myMap_->longest_path_length_1 = atoi(s);
                        
                        //cout << myMap_->DFF_id << endl;
                        //cout << myMap_->P0 << endl;
                        //cout << myMap_->P1 << endl;
                        
                        int temp, key;
                        fin.getline(line_buffer, MAX_LINE_LENGTH);
                        s = strtok(line_buffer, "\t\n");
                        if(s != NULL){
                                bool even = true;
                                temp = atoi(s);
                                myMap_->R0_seq.insert(temp);
                                key = temp;
                                //cout << temp << "\t";
                                while(1){
                                        s = strtok(NULL, " \t\n");
                                        if(s == NULL)
                                                break;
                                                
                                        if(even == true){
                                                temp = atoi(s);
                                                myMap_->R0_seq_res_len[key] = temp;
                                        }
                                        else{
                                                temp = atoi(s);
                                                myMap_->R0_seq.insert(temp);
                                                key = temp;
                                        }
                                                
                                        even = !even;
                                        //cout << temp << "\t";
                                }
                                //cout << endl;
                        }
                                
                        fin.getline(line_buffer, MAX_LINE_LENGTH);
                        s = strtok(line_buffer, "\t\n");
                        if(s == NULL)
                                continue;
                        
                        temp = atoi(s);
                        myMap_->R1_seq.insert(temp);
                        key = temp;
                        bool even = true;
                        //cout << temp << "\t";
                        while(1){
                                s = strtok(NULL, " \t\n");
                                if(s == NULL)
                                        break;
                                        
                                if(even == true){
                                        temp = atoi(s);
                                        myMap_->R1_seq_res_len[key] = temp;
                                }
                                else{
                                        temp = atoi(s);
                                        key = temp;
                                        myMap_->R1_seq.insert(temp);
                                }
                                        
                                even = !even;
                                //cout << temp << "\t";
                        }
                        //cout << endl;
                        
                        Mymap[idx].push_back(myMap_);
                }
                
                vector<TresMap*>::iterator it_map;
                for(int i=0; i<Ci->flipflopSize(); ++i){
                        for(it_map = Mymap[idx].begin(); it_map != Mymap[idx].end(); it_map++){
                                if((*it_map)->DFF_id == i)
                                        break;
                        }
                        
                        if(it_map == Mymap[idx].end())
                                islands.push_back(i);
                }
                        
                cout << "In original mode, island flipflop's percentage is " << 1.0 - ((double) Mymap[idx].size() / (double) Ci->flipflopSize()) << endl;
        }
        
}


void Simulate::multimodeResMapGen(const char* filename, vector<TresMap*> *Mymap, bool batch, bool writeToFile){
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<int>::iterator it_vec;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;

        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        if(batch == false){
                for(i = 0; i < Ci->signalSize(); ++i) {
                        Ci->getSignal(i)->P0_array = new float[1];
                        Ci->getSignal(i)->P1_array = new float[1];
                        Ci->getSignal(i)->RR_array = new double[1];
                }
        }
        else{
                for(i = 0; i < Ci->signalSize(); ++i) {
                        Ci->getSignal(i)->P0_array = new float[assign_file_id];
                        Ci->getSignal(i)->P1_array = new float[assign_file_id];
                        Ci->getSignal(i)->RR_array = new double[assign_file_id];
                }
        }
        
        double RL_gen_time = 0.0;
        struct timeval start1, finish1, finish2, finish3;
        
        gettimeofday(&start1, NULL);
        //----------------------------------------MIN--------------------------------------
        if(batch == true){
                for(j = 0; j < assign_file_id; j++){
                        for(i=0; i<Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                        
                        string tmp1 = filename;
                        tmp1.erase(tmp1.begin() + tmp1.find("bench"), tmp1.end());
                        tmp1 += "assign";
                        
                        initSimulate(tmp);
                        cout << "sim init value starts" << endl;
                        cout << "current mode is " << j << endl;
                        LoadDFFMap(filename, j);
                        cout << "sim init value ends" << endl;
                
                        string tmp2 = filename;
                        tmp2 += ".prob_";
                        stringstream ss;
                        ss << j;
                        tmp2 += ss.str();
                        cout << tmp2 << endl;
                        Ci->read_prob(j, tmp2);
                        
                        //finish collecting resMap
                        for(i = 0; i < Ci->flipflopSize(); ++i)
                        {
                                cout << "i is " << i << endl;
                                flag = 0;
                                TresMap* MyresMap = new TresMap;
                                clearTraced();
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(true);
                                addTraced(Ci->getFlipflop(i)->getOutput(0));
                
                                assert(tracedSigs.size() == 1);
                
                                MyresMap->DFF_id = i;
                                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->P0_array[j];
                                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->P1_array[j];
                                
                                initSimulateHybrid();
                                PreSimHybrid1Trace();
                        
                                for(int t=0; t<Ci->signalSize(); ++t)
                                        Ci->getSignal(t)->stored = 0;
                                
                                for(k = 0; k<Ci->flipflopSize(); ++k)
                                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                                Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                                simHybrid1Trace(true);
                
                                for(k = 0; k<Ci->flipflopSize(); ++k)
                                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
                                        {
                                                if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                                   Ci->getFlipflop(k)->getOutput(0)->preset == false)
                                                {
                                                        flag = 1;
                                                        MyresMap->R1_seq.insert(k);
                                                }
                                        }
                
                                for(k = 0; k<Ci->gateSize(); ++k){        
                                        if(Ci->getGate(k)->getOutput(0)->isKnown()){
                                                if(Ci->getGate(k)->IsCritical == true){
                                                        MyresMap->R1_com.insert(k);
                                                }
                                        }
                                }
                
                                //findAvgLength(i, MyresMap, 1);
                                
                                initSimulateHybrid();
                                PreSimHybrid1Trace();
                
                                for(k = 0; k<Ci->flipflopSize(); ++k)
                                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                                Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                                for(int t=0; t<Ci->signalSize(); ++t)
                                        Ci->getSignal(t)->stored = 0;
                
                                simHybrid1Trace(false);
                
                                int count_res0 = 0;
                                for(k = 0; k<Ci->flipflopSize(); ++k)
                                        if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
                                                if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                                   Ci->getFlipflop(k)->getOutput(0)->preset == false){
                                                        flag = 1;
                                                        MyresMap->R0_seq.insert(k);
                                                        count_res0++;
                                                }
                
                                for(k = 0; k<Ci->gateSize(); ++k){        
                                        if(Ci->getGate(k)->getOutput(0)->isKnown()){
                                                if(Ci->getGate(k)->IsCritical == true){
                                                        flag = 1;
                                                        MyresMap->R0_com.insert(k);
                                                }
                                        }
                                }
                
                                //findAvgLength(i, MyresMap, 0);
                                
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                                
                                if(MyresMap->R0_seq.size() || MyresMap->R1_seq.size())
                                        Mymap[j].push_back(MyresMap);
                                else {
                                        if(j == 0)//one island set
                                                islands.push_back(i);//may have problem
                                }
                        }
                }
        }
        else{
                for(i=0; i<Ci->flipflopSize(); ++i)
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                
                string tmp1 = filename;
                tmp1.erase(tmp1.begin() + tmp1.find("bench"), tmp1.end());
                tmp1 += "assign";
                
                initSimulate(tmp);
                cout << "sim init value starts" << endl;
                cout << "In single mode " << endl;
                LoadDFFMap(filename, assign_file_id);
                cout << "sim init value ends" << endl;
                
                if(assign_file_id == -1){
                        string tmp2 = filename;
                        tmp2 += ".prob";
                        cout << "Prob file name is " << tmp2 << endl;
                        Ci->read_prob(&tmp2[0]);
                }
                else{
                        string tmp2 = filename;
                        tmp2 += ".prob_";
                        stringstream ss;
                        ss << assign_file_id;
                        tmp2 += ss.str();
                        cout << tmp2 << endl;
                        Ci->read_prob(0, tmp2);
                }
                
                //finish collecting resMap
                for(i = 0; i < Ci->flipflopSize(); ++i)
                {
                        flag = 0;
                        TresMap* MyresMap = new TresMap;
                        clearTraced();
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(true);
                        addTraced(Ci->getFlipflop(i)->getOutput(0));
                                
                        assert(tracedSigs.size() == 1);
                
                        MyresMap->DFF_id = i;
                        if(assign_file_id != -1){
                                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->P0_array[0];
                                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->P1_array[0];
                        }
                        else{
                                MyresMap->P0 = Ci->getFlipflop(i)->getOutput(0)->P0;
                                MyresMap->P1 = Ci->getFlipflop(i)->getOutput(0)->P1;
                        }
                                
                        initSimulateHybrid();
                        PreSimHybrid1Trace();
                        
                        for(int t=0; t<Ci->signalSize(); ++t)
                                Ci->getSignal(t)->stored = 0;
                
                        for(k = 0; k<Ci->flipflopSize(); ++k)
                                if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                        Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                        simHybrid1Trace(true);
                
                        for(k = 0; k<Ci->flipflopSize(); ++k)
                                if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
                                {
                                        if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                           Ci->getFlipflop(k)->getOutput(0)->preset == false){
                                                flag = 1;
                                                MyresMap->R1_seq.insert(k);
                                        }
                                }
                        
                        for(k = 0; k<Ci->gateSize(); ++k){        
                                if(Ci->getGate(k)->getOutput(0)->isKnown()){
                                        if(Ci->getGate(k)->IsCritical == true){
                                                MyresMap->R1_com.insert(k);
                                        }
                                }
                        }
                
                        //findAvgLength(i, MyresMap, 1);
                        
                        initSimulateHybrid();
                        PreSimHybrid1Trace();
                
                        for(k = 0; k<Ci->flipflopSize(); ++k)
                                if(Ci->getFlipflop(k)->getOutput(0)->isKnown() && Ci->getFlipflop(k)->getOutput(0)->getTraced() == false)
                                        Ci->getFlipflop(k)->getOutput(0)->preset = true;
                
                        for(int t=0; t<Ci->signalSize(); ++t)
                                Ci->getSignal(t)->stored = 0;
                        
                        simHybrid1Trace(false);
                
                        int count_res0 = 0;
                        for(k = 0; k<Ci->flipflopSize(); ++k)
                                if(Ci->getFlipflop(k)->getOutput(0)->isKnown())
                                        if(Ci->getFlipflop(k)->getOutput(0)->getTraced() == false &&
                                           Ci->getFlipflop(k)->getOutput(0)->preset == false){
                                                flag = 1;
                                                MyresMap->R0_seq.insert(k);
                                                count_res0++;
                                        }
                        
                        for(k = 0; k<Ci->gateSize(); ++k){        
                                if(Ci->getGate(k)->getOutput(0)->isKnown()){
                                        if(Ci->getGate(k)->IsCritical == true){
                                                flag = 1;
                                                MyresMap->R0_com.insert(k);
                                        }
                                }
                        }
                        
                        //findAvgLength(i, MyresMap, 0);
                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false);
                
                        if(MyresMap->R0_seq.size() || MyresMap->R1_seq.size())
                                Mymap[0].push_back(MyresMap);
                        else 
                                islands.push_back(i);
                }
        }
        
        gettimeofday(&finish1, NULL);       
        cout << "the percentage of island flipflops is " << (double)islands.size() / (double)Ci->flipflopSize() << endl;
        cout<< "total runtime for generating reachability list for different modes is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        string tmp_ = filename;
        tmp_.erase(tmp_.begin() + tmp_.find("bench"), tmp_.end());
        tmp_ += "resmap";
        string tmp_bck = tmp_;
        
        if(writeToFile == false)
                return;
        
        if(batch == true){
                for(i = 0; i < assign_file_id; i++){        
                        tmp_ = tmp_bck;
                        stringstream ss;
                        ss << j;
                        tmp_ += "_" + ss.str();
                        cout << "res map name is " << tmp_ << endl;
                        ofstream out(tmp_.c_str());
                        set<int>::iterator it_RM;
        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++)
                        {
                                //assert((*it_map)->R0_seq.size() == (*it_map)->R0_seq_res_len.size());
                                //assert((*it_map)->R1_seq.size() == (*it_map)->R1_seq_res_len.size());
                                
                                out << (*it_map)->DFF_id << "\t" << (*it_map)->P0 << "\t" << (*it_map)->P1 
                                    << "\t" << (*it_map)->longest_path_length_0 << "\t" << (*it_map)->longest_path_length_1<< endl;                  
                                for(it_RM = (*it_map)->R0_seq.begin(); it_RM != (*it_map)->R0_seq.end(); it_RM++)
                                        out << (*it_RM) << "\t" << (*it_map)->R0_seq_res_len[*it_RM] << "\t" ;
                                out<<endl;        
                                
                                for(it_RM = (*it_map)->R1_seq.begin(); it_RM != (*it_map)->R1_seq.end(); it_RM++)
                                        out << (*it_RM) << "\t" << (*it_map)->R1_seq_res_len[*it_RM] << "\t" ;
                                out<<endl;
                        }
                        out.close();
                }        
        }
        else{
                tmp_ = tmp_bck;
                stringstream ss;
                ss << assign_file_id;
                if(assign_file_id != -1)
                        tmp_ += "_" + ss.str();
                
                ofstream out(tmp_.c_str());
                set<int>::iterator it_RM;
        
                for(it_map = Mymap[0].begin();it_map != Mymap[0].end();it_map++)
                {
                        //assert((*it_map)->R0_seq.size() == (*it_map)->R0_seq_res_len.size());
                        //assert((*it_map)->R1_seq.size() == (*it_map)->R1_seq_res_len.size());
                        
                        out << (*it_map)->DFF_id << "\t" << (*it_map)->P0 << "\t" << (*it_map)->P1 
                            << "\t" << (*it_map)->longest_path_length_0 << "\t" << (*it_map)->longest_path_length_1<< endl;                  
                        for(it_RM = (*it_map)->R0_seq.begin(); it_RM != (*it_map)->R0_seq.end(); it_RM++)
                                out << (*it_RM) << "\t" << (*it_map)->R0_seq_res_len[*it_RM] << "\t" ;
                        out<<endl;        
                        
                        for(it_RM = (*it_map)->R1_seq.begin(); it_RM != (*it_map)->R1_seq.end(); it_RM++)
                                out << (*it_RM) << "\t" << (*it_map)->R1_seq_res_len[*it_RM] << "\t" ;
                        out<<endl;
                        
                }
                out.close();
        }
}


void Simulate::assignRandomWeight(const int crit_gate_num){
        
        int k, count = 0;
        double criticality;
        const long rand_max = 2e10;

        for(k=0; k<Ci->gateSize(); ++k){
                Ci->getGate(k)->IsCritical = false;
                Ci->getGate(k)->weight = 0.0;
        }
        
        while(count < crit_gate_num){
                
                k = rand() % Ci->gateSize();
                criticality = (double) (rand() % rand_max) / (double) rand_max;
                assert(fabs(criticality) < 1.0);
                
                Ci->getGate(k)->IsCritical = true;
                Ci->getGate(k)->weight = criticality;
                //Ci->getGate(k)->weight = 0.0;
                
                count++;
        }
}


std::pair<double, double> Simulate::Check_Traces_SRR_GRR(string filename)
{
        int trace_num, flag;
        int cur_size = 0;
        string name;
        
        stringstream ss;
        ss << assign_file_id;
        
        string tmp1 = filename;
        tmp1.erase(tmp1.begin() + tmp1.find("bench"), tmp1.end());
        if(assign_file_id != -1){
                tmp1 += "init_dff_val_";
                tmp1 += ss.str();        
        }
        else
                tmp1 += "init_dff_val";
        cout << tmp1 << endl;
        
        const int MAX_LINE_LENGTH = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        strcpy(line_buffer, "");
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        //str += "trace_check_06_25_13_";
        str += "trace_check_06_29_13";
        //str += "trace_check_ILP0";
        //str += "trace_check_ILP_hamid";
        //if(assign_file_id != -1) //commented for trace_check_06_25_13_
        //str += ss.str();
        
        //str += ss.str();        
        cout << str << endl;
        
        ifstream in(str.c_str());
        if (!in.is_open()) {
                cerr << "Can't open trace check file" << endl;
                exit(1);
        }
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        if(assign_file_id != -1){
                tmp += "assign_";
                tmp += ss.str();
        }
        else
                tmp += "assign";
        cout << "Assign filename is " << tmp << endl;
        
        ifstream in_assign(tmp.c_str());
        if(!in_assign.is_open()){
                cout << "Open assign file failed!" << endl;
                exit(1);
        }
        
        myDataType f,g;
        int data; char pin_name[50];
        while(!in_assign.eof()){
                flag = 0;
                in_assign.getline(line_buffer, MAX_LINE_LENGTH);
                sscanf (line_buffer, "%s\t%d", pin_name, &data);
                tmp = pin_name;
                cout << "pin is " << tmp;
                for(int i=0; i<Ci->signalSize(); ++i){
                        if(Ci->getSignal(i)->getName() == tmp){
                                flag = 1;
                                cout << "\tvalue is " << data << endl;
                                Ci->getSignal(i)->untouchible = true;
                                if(data == 1){
                                        f.assign((BIT_TYPE)1);
                                        g = f;
                                        for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); k++)
                                        {
                                                f = f << 1;
                                                f = f | g;
                                        }
                                        
                                        Ci->getSignal(i)->Mult_Val0[0] = f;
                                        Ci->getSignal(i)->Mult_Val1[0] = f;
                                }
                                else{
                                        Ci->getSignal(i)->Mult_Val0[0].assign((BIT_TYPE)0);
                                        Ci->getSignal(i)->Mult_Val1[0].assign((BIT_TYPE)0);
                                }
                                
                                break;
                        }
                }
                
                assert(flag == 1);
        }
        
        //initSimulate();
        initSimulate(filename);
        //SimInitDFFValue();
        LoadDFFMap(filename, assign_file_id);
        
        while(1){

                in.getline(line_buffer, MAX_LINE_LENGTH);
                
                if(!strcmp(line_buffer, "&&&"))
                        break;
                else if(!strcmp(line_buffer, "!")){
                }
                else{
                        cout << "New set of traced flipflops: " << endl;
                        trace_num = atoi(line_buffer);
                        //assert(trace_num == 8 || trace_num == 16 || trace_num == 32);

                        clearTraced();
                        for(int i = 0; i<Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);

                        for(int j = 0; j < trace_num; j++){

                                flag = 0;
                                in.getline(line_buffer, MAX_LINE_LENGTH);
                                name = line_buffer;
                                
                                for(int i = 0; i<Ci->flipflopSize(); ++i)
                                {
                                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == name)
                                        {
                                                Ci->getFlipflop(i)->getOutput(0)->setTraced(true,0);
                                                addTraced(Ci->getFlipflop(i)->getOutput(0));
                                                //cout << name << endl;
                                                flag = 1; break;
                                        }
                                }
                        
                                assert(flag == 1);
                        }

                        double total_VN = 0.0;
                        int seed_num = 3;
                        cout << "seed num is " << seed_num << endl;
                
                        double tmp_SRR = 0.0;
                        double tmp_GRR = 0.0;
                        std::pair<double, double> SRR_GRR;

                        for(int i = 0; i < seed_num; i++)
                        {
                                initMultThread(1);
                                LoadInitDFFValue(i, 0);
                                //SRR_GRR = reportSRR_GRR();
                                //tmp_SRR += SRR_GRR.first;
                                //tmp_GRR += SRR_GRR.second;
                                
                                tmp_SRR += MultCalVNWOLOCK(0);
                                //total_VN += MultCalVN(0);
                        }

                        cout << "For selecting " << tracedSigs.size() << " of flipflops: " << endl;
                        cout << "SRR is " << tmp_SRR / seed_num << "\t";
                        cout << "GRR is " << tmp_GRR / seed_num << endl;
                }        
        }
        
        return make_pair(0.0, 0.0);
}


pair<double, double> Simulate::multimodeSAProcess(const int trace_size, vector<TresMap*> *Mymap, vector<int> &selected_traces, const char* filename){
        
        int i, j, k;
        double weight, temp_weight;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> *MR;
        MR = new vector<TmapRate>[assign_file_id];
        //assert(selected_traces.size() == 0);
        
        cout << "file name is " << filename << endl;        
        //string tmp = filename;
        //tmp += "_report";
        //ofstream report(tmp.c_str());
        //report<< Ci->flipflopSize() <<endl;
        
        double t_weight_compute = 0.0; //parallelizable
        double t_pick_best = 0.0; //serial
        double t_add_islands = 0.0; //serial
        double t_update_RR = 0.0; //parallelizable
        struct timeval start1, start2, finish1, finish2, finish3;
        gettimeofday(&start1, NULL);
        /*
        if(selected_traces.size() != trace_size){
                cout << "Discrepency exists between the existing solution and the required trace size!" << endl;
                cout << "selected trace size is " << selected_traces.size();
                cout << "\trequired trace size is " << trace_size << endl;
        }
        */
        double VN_final;
        while(selected_traces.size() < trace_size)
        {
                gettimeofday(&start2, NULL);                
                for(i = 0; i < assign_file_id; i++){
                        
                        MR[i].clear();
                        weight = 0.0;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++)
                        {
                                temp_weight =0.0;
                                for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                                {
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0),(*it_map)->P0);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R0_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_0 + 0.0000001)) * (*it_map)->P0);
                                }
                                
                                for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++){
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R1_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_1 + 0.0000001)) * (*it_map)->P1);
                                }
                                
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                                
                                TmapRate myMR;
                                myMR.weight = temp_weight;
                                myMR.it_map = it_map;
                                myMR.DFF_id = (*it_map)->DFF_id;
                                MR[i].push_back(myMR);
                        }
                        
                        if(weight == 0.0)
                                break;
                
                        std::sort(MR[i].begin(), MR[i].end(), TrateMapSort);        
                }
                
                gettimeofday(&finish1, NULL);
                t_weight_compute += (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                gettimeofday(&start2, NULL);                
                
                vector<TmapRate> MR_t;
                TmapRate myMR;
                
                float *scores = new float[Ci->flipflopSize()]; 
                memset(scores, 0.0, Ci->flipflopSize()*sizeof(float));
                
                for(i = 0; i < assign_file_id; i++)
                        for(j = 0; j < MR[i].size(); j++)
                                scores[MR[i][j].DFF_id] += MR[i][j].weight;
                
                for(i = 0; i < Ci->flipflopSize(); i++)
                {
                        myMR.weight = scores[i];
                        myMR.it_map = it_map;
                        myMR.DFF_id = i;
                        MR_t.push_back(myMR);
                }
                
                delete [] scores;
                std::sort(MR_t.begin(), MR_t.end(), TrateMapSort);        
                
                cout << "Higest impact weight is " << MR_t[0].weight << endl;
                const double topK = 0.03;
                MR_t.resize(floor(MR_t.size() * topK));
                for(j = 0; j < MR_t.size(); j++)
                        MR_t[j].weight = 0.0;
                
                assert(j != 0);
                cout << "Top candidate size is " << MR_t.size() << endl;
                
                for(int l = 0; l < assign_file_id; l++){
                        
                        initSimulate(filename);
                        LoadDFFMap(filename, l);
                        
                        k = MR_t.size();
                        int pos = 0;
                        const int tot_thread_num = MR_t.size();
                
                        while(k > 0){
                        
                                int thread_num;
                                if(k >= THREAD_NUM_T)
                                        thread_num = THREAD_NUM_T;
                                else
                                        thread_num = k % THREAD_NUM_T;
                        
                                pthread_t PTs[thread_num];
                        
                                //cout << "thread_num is " << thread_num << endl;
                                for(j = 0; j < thread_num; j++)
                                {
                                        for(i=0; i < Ci->flipflopSize(); ++i)
                                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                                
                                        for(i=0; i < selected_traces.size(); ++i)
                                                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                                        //cout << "see" << (*(MR[j].it_map))->DFF_id << endl;
                                        Ci->getFlipflop(MR_t[pos + j].DFF_id)->getOutput(0)->setTraced(true,j);
                                }
                        
                                int seed_num = 0;
                                while(seed_num < 3)
                                {
                                        if(selected_traces.size())
                                                initACCMultThread_MM(thread_num, seed_num, l);
                                        else
                                                initMultThread(thread_num);
                                        
                                        myWorkarg* mwa= new myWorkarg[thread_num];
                                        for(j = 0; j < thread_num; j++)
                                        {
                                                mwa[j].Tid = j;
                                                mwa[j].Sim = this;
                                                LoadInitDFFValue(seed_num, j);
                                                pthread_create(&PTs[j], NULL, work, (void*)(&mwa[j]));
                                        }
                                        
                                        for(j = 0; j < thread_num; j++)
                                        {
                                                myRetarg* mra = new myRetarg;
                                                pthread_join(PTs[j], (void**) &mra);
                                                
                                                MR_t[pos + mra->Tid].weight += mra->VN;
                                                delete mra;
                                        }
                                        
                                        delete [] mwa;
                                        seed_num++;        
                                }
                                
                                delete [] sigList;
                                delete [] CurSig;
                                
                                k -= thread_num;
                                pos += thread_num;
                        }
                        assert(pos == tot_thread_num);
                }
                
                std::sort(MR_t.begin(), MR_t.end(), TrateMapSort);
                
                int best_cand = MR_t[0].DFF_id;
                
                gettimeofday(&finish1, NULL);
                t_pick_best += (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start2, NULL);
                assert(best_cand != -1);
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                
                selected_traces.push_back(best_cand);
                
                for(j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);

                //generate ref values
                double VN_bar = 0.0;
                for( i = 0; i < assign_file_id; i++){
                        
                        initSimulate(filename);
                        LoadDFFMap(filename, i);
                        
                        int seed_num = 0;
                        double cur_VN = 0.0;
                
                        while(seed_num < 3){
                                
                                initMultThread(1);
                                LoadInitDFFValue(seed_num,0);
                                cur_VN += MultCalVNWOLOCK(0);
                                
                                for(j = 0; j < Ci->signalSize(); ++j){
                                        Ci->getSignal(j)->Mult_Val0_ref_MM[seed_num][i] = Ci->getSignal(j)->Mult_Val0[0];
                                        Ci->getSignal(j)->Mult_Val1_ref_MM[seed_num][i] = Ci->getSignal(j)->Mult_Val1[0];
                                }
                                
                                double restime = 0.0;
                                for(j = 0; j < Ci->flipflopSize(); ++j)
                                {
                                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                                        Ci->getFlipflop(j)->getOutput(0)->RR_array[seed_num] += restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                                }
                                
                                seed_num++;
                        }
                        
                        for(j=0; j<Ci->flipflopSize(); ++j)
                                Ci->getFlipflop(j)->getOutput(0)->RR_array[i] /= 3;
                        
                        cout << "VN for mode " << i << " is "<< cur_VN / 3 <<endl;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++){
                                if((*it_map)->DFF_id == best_cand){
                                        Mymap[i].erase(it_map);
                                        break;
                                }
                        }
                        
                        VN_bar += cur_VN / 3;
                }
                
                VN_final = VN_bar;
                gettimeofday(&finish1, NULL);
                t_update_RR += (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
        }
        
        gettimeofday(&finish1, NULL);
        
        cout<< "total runtime for Simulation-Based trace selection for one round of the Simulation Anealing is " << trace_size << " is " 
            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //t_pick_best serial
        t_weight_compute /= assign_file_id; //parallelizable
        t_update_RR /= assign_file_id; //parallelizable
        cout << "After parallelization, ideal time for weight computation is " << t_weight_compute << endl;
        cout << "Pick best time is " << t_pick_best << endl;
        cout << "After parallelization, ideal time for update RR is " << t_update_RR << endl;

        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        /*
        cout<< "seleted signals' outputs names are...." << endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName() << " ";
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        cout << endl;
        */
        return make_pair(VN_final, 0.0);
}


void Simulate::pickRemovedTraces(vector<int> & selected_traces, list<int>& removedTraces, unsigned int step_size, const char* filename){
        //step_size is currently of no use...
        int i, j, k, l;
        vector<TmapRate> MR;
        vector<TresMap*>::iterator it_map;
        removedTraces.clear();
        
        for(i = 0; i < selected_traces.size(); ++i){
                TmapRate myMR;
                myMR.weight = 0.0;
                myMR.it_map = it_map;
                myMR.DFF_id = selected_traces[i];
                MR.push_back(myMR);
        }
        
        for(l = 0; l < assign_file_id; l++){
                
                initSimulate(filename);
                LoadDFFMap(filename, l);
                
                k = MR.size();
                int pos = 0;
                const int tot_thread_num = MR.size();
                
                while(k > 0){
                        
                        int thread_num;
                        if(k >= THREAD_NUM_T)
                                thread_num = THREAD_NUM_T;
                        else
                                thread_num = k % THREAD_NUM_T;
                        
                        pthread_t PTs[thread_num];
                        
                        //cout << "thread_num is " << thread_num << endl;
                        for(j = 0; j < thread_num; j++)
                        {
                                for(i=0; i < Ci->flipflopSize(); ++i)
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                                
                                for(i=0; i < selected_traces.size(); ++i)
                                        Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                                Ci->getFlipflop(MR[pos + j].DFF_id)->getOutput(0)->setTraced(false,j);
                        }
                        
                        int seed_num = 0;
                        while(seed_num < 3)
                        {
                                initMultThread(thread_num);
                                
                                myWorkarg* mwa= new myWorkarg[thread_num];
                                for(j = 0; j < thread_num; j++)
                                {
                                        mwa[j].Tid = j;
                                        mwa[j].Sim = this;
                                        LoadInitDFFValue(seed_num, j);
                                        pthread_create(&PTs[j], NULL, work, (void*)(&mwa[j]));
                                }
                                
                                for(j = 0; j < thread_num; j++)
                                {
                                        myRetarg* mra = new myRetarg;
                                        pthread_join(PTs[j], (void**) &mra);
                                        
                                        MR[pos + mra->Tid].weight += mra->VN;
                                        delete mra;
                                }
                                
                                delete [] mwa;
                                //for(i=0; i<Ci->flipflopSize(); ++i)
                                //delete[] TEMP_VA[i];
                                
                                //delete[] TEMP_VA;
        
                                seed_num++;
                        }
                        
                        delete [] sigList;
                        delete [] CurSig;        
                                
                        k -= thread_num;
                        pos += thread_num;
                }
                
                assert(pos == tot_thread_num);
        }
        
        std::sort(MR.begin(), MR.end(), TrateMapSort);
        
        for(i = 0; i < MR.size(); i++)
                removedTraces.push_back(MR[i].DFF_id);
}


std::pair<double, double> Simulate::multimodeSimulateAnealing(const int trace_size, const char* filename)
{
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<TresMap*> *Mymap;
        Mymap = new vector<TresMap*>[assign_file_id];
        
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_RM;
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int>* myTraceSet;
        myTraceSet = new vector<int>[assign_file_id];
        
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        for(i = 0; i < Ci->signalSize(); ++i) {
                Ci->getSignal(i)->P0_array = new float[assign_file_id];
                Ci->getSignal(i)->P1_array = new float[assign_file_id];
                Ci->getSignal(i)->RR_array = new double[assign_file_id];
        }
        
        double RL_gen_time = 0.0;
        struct timeval start1, finish1, finish2, finish3;
        
        gettimeofday(&start1, NULL);
        readResMap(filename, Mymap, true, -1);
        readMultiSolution(filename, myTraceSet);
        gettimeofday(&finish1, NULL);       
        cout<< "total runtime for reading reachability lists and solutions from different modes is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //------------------------------Simulate Anealing-----------------------------------------
        //random pick an init solution
        int sol_id = -1;
        long RL_size = 0;
        const int total_mode_num = assign_file_id;
        
        long cur_best = 0.0;
        //double* scores = new double[total_mode_num];
        //memset(scores, 0.0, sizeof(double) * total_mode_num);
        //sol_id = 0;//take the first whcih is the current best
        
        for(int l = 0; l < total_mode_num; l++){
                for(it_map = Mymap[l].begin(); it_map != Mymap[l].end(); it_map++)
                        RL_size += (*it_map)->R0_seq.size() + (*it_map)->R1_seq.size();
                
                if(cur_best < ((double)RL_size / (double)total_mode_num)){
                        cur_best = ((double)RL_size / (double)total_mode_num);
                        sol_id = l;
                }
        }
        //sol_id = 1;
        cout << "Take initial solution generated from mode " << sol_id << endl;
        
        vector<int> selected_traces(myTraceSet[sol_id]);
        vector<int> cur_best_traces(selected_traces);
        vector<int> overall_best_traces(selected_traces);
        
        //set init temperature
        double T = 10000.0;
        double cur_best_SRR = 0.0;// give an initial value
        double overall_best_SRR = 0.0;// give an initial value
        const double T_min = 1.0;
        const double alpha = 0.95;
        //unsigned int step_size = rand() % 3 + 1;
        unsigned int step_size = 1;
        
        gettimeofday(&start1, NULL);
        list<int> ruleout_rank, ruleout_rank_temp;
        //pickRemovedTraces(selected_traces, ruleout_rank, 1, filename);
        
        const int MAX_ITR_CNT = 1000;
        double MAX_RUNTIME;
        const double delta_gap = 8.0;
        
        if(tmp.find("b17") != string::npos || tmp.find("S3") != string::npos)
                MAX_RUNTIME = 2400.0;
        else if(tmp.find("b18") != string::npos || tmp.find("des_perf") != string::npos)
                MAX_RUNTIME = 4800.0;
        else if(tmp.find("dsp") != string::npos || tmp.find("DMA") != string::npos)
                MAX_RUNTIME = 14400.0;//3600.00
        else
                MAX_RUNTIME = 7200.0;
        
        cout << "MAX runtime is " << MAX_RUNTIME << endl;
        
        const int interval = TEST_CASE_NUM * TRACE_DEPTH_NUM * 8 * sizeof(BIT_TYPE);
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->valArray = new Value[interval];
        
        i = 0;
        long no_improv_cnt = 0;
        bool rand_sel = false;
        
        while(i < MAX_ITR_CNT){
                cout << "iteration " << i << " step size " << step_size << " rand_sel? " << rand_sel << endl;
                cout << "Temperatue is " << T << endl;
                selected_traces = cur_best_traces;
                if(i % 8 == 0)
                        pickRemovedTraces(selected_traces, ruleout_rank, 1, filename);
                ruleout_rank_temp = ruleout_rank;
                assert(selected_traces.size() == ruleout_rank_temp.size());
                
                //select the eliminated traces
                if(rand_sel == false){
                        for(j = 0; j < step_size; j++){
                                int rule_out_trace = ruleout_rank_temp.front();
                                cout << "removed trace is " << Ci->getFlipflop(rule_out_trace)->getOutput(0)->getName() <<endl;
                                it_vec = find(selected_traces.begin(), selected_traces.end(), rule_out_trace);
                                assert(it_vec != selected_traces.end());
                                selected_traces.erase(it_vec);
                                ruleout_rank_temp.pop_front();
                        }
                }
                else{
                        for(j = 0; j < step_size; j++){
                                int temp = rand() % selected_traces.size();
                                selected_traces.erase(selected_traces.begin() + temp);
                                cout << "removed trace is " << Ci->getFlipflop(selected_traces[temp])->getOutput(0)->getName() <<endl;
                                list<int>::iterator it_list;
                                it_list = find(ruleout_rank_temp.begin(), ruleout_rank_temp.end(), selected_traces[temp]);
                                assert(it_list != ruleout_rank_temp.end());
                                ruleout_rank_temp.erase(it_list);
                        }
                }
                
                //pick the one with the highest impact weights and add inside
                pair<double, double> SRR_GRR;
                SRR_GRR = multimodeSAProcess(trace_size, Mymap, selected_traces, filename);
                cout << "SRR of this round " << SRR_GRR.first << "\tCurrent best SRR " << cur_best_SRR << endl;
                if(SRR_GRR.first > cur_best_SRR){
                        cur_best_SRR = SRR_GRR.first;
                        swap(cur_best_traces, selected_traces);
                        
                        if(cur_best_SRR > overall_best_SRR){
                                overall_best_SRR = cur_best_SRR;
                                overall_best_traces = cur_best_traces;
                        }
                        
                        for(j = 0; j < step_size; j++)
                                ruleout_rank_temp.push_back(cur_best_traces.back() - j);
                        
                        step_size = 1;
                        no_improv_cnt = 0;
                        ruleout_rank = ruleout_rank_temp;
                        rand_sel = false;
                        T = T * alpha;
                        cout << "good!" << endl;
                }
                else{
                        unsigned int temp = rand() % 65536;
                        double r = (double)temp / 65536.0;
                        double gap = cur_best_SRR - SRR_GRR.first;
                        double p = (SRR_GRR.first - cur_best_SRR) / T;
                        
                        no_improv_cnt++;
                        if(exp(p) > r){
                                cur_best_SRR = SRR_GRR.first;
                                swap(cur_best_traces, selected_traces);
                                
                                for(j = 0; j < step_size; j++)
                                        ruleout_rank_temp.push_back(cur_best_traces.back() - j);
                                
                                ruleout_rank = ruleout_rank_temp;
                                rand_sel = false;
                                T = T * alpha;
                                
                                //if(gap > delta_gap)
                                //step_size++;
                                
                                cout << "good!" << endl;
                        }
                        else{
                                step_size++;
                                cout << "no good!" << endl;
                        }
                }
                
                i++;
                
                if(step_size > 3)
                {
                        step_size = 1;
                        rand_sel = true;
                }
                
                gettimeofday(&finish1, NULL);
                if(no_improv_cnt == 20){
                        cout << "no improvement for 20 itrs" << endl;
                        break;
                }
                if(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0) > MAX_RUNTIME)
                        break;
        }
        
        //gettimeofday(&finish1, NULL);
        cout << "The number of rounds for doing SA is " << i << endl;
        cout<< "total runtime for Simulate Anealing is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        cout << "overall best SRR is " << overall_best_SRR <<endl;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                delete [] Ci->getFlipflop(i)->getOutput(0)->valArray;
                
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "trace_check_ILP0";
        ofstream out(str.c_str());
        out << overall_best_traces.size() << endl;
        for(i = 0; i < overall_best_traces.size(); i++){
                cout << Ci->getFlipflop(overall_best_traces[i])->getOutput(0)->getName() << " ";
                out << Ci->getFlipflop(overall_best_traces[i])->getOutput(0)->getName() << endl;
        }
        cout << endl;
        out << "!" << endl;
        out << "&&&";
        out.close();
        
        //------------------------------Simulate Anealing-----------------------------------------
        std::pair<double, double> SRR_GRR;
        for(i = 0; i < total_mode_num; i++){
                assign_file_id = i;
                //SRR_GRR = Check_Traces_SRR_GRR(filename);
                const double init_SRR = SRR_GRR.first;
                cout << "Initial SRR is " << init_SRR << "\t";
                cout << "Initial GRR is " << SRR_GRR.second << endl;
        }
        
        return SRR_GRR;
}


pair<double, double> Simulate::multimodeSASingleModeProcess(const int trace_size, vector<TresMap*> *Mymap, vector<int> &selected_traces, const char* filename){
        
        int i, j, k;
        double weight, temp_weight;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> *MR;
        MR = new vector<TmapRate>[1];
        assert(selected_traces.size() == 0);
        
        cout << "file name is " << filename << endl;        
        string tmp = filename;
        tmp += "_report";
        ofstream report(tmp.c_str());
        report<< Ci->flipflopSize() <<endl;
        
        double t_weight_compute = 0.0; //parallelizable
        double t_pick_best = 0.0; //serial
        double t_add_islands = 0.0; //serial
        double t_update_RR = 0.0; //parallelizable
        struct timeval start1, start2, finish1, finish2, finish3;
        gettimeofday(&start1, NULL);
        
        double VN_final;
        initSimulate(filename);
        LoadDFFMap(filename, assign_file_id);
                
        while(selected_traces.size() < trace_size)
        {
                gettimeofday(&start2, NULL);                
                
                MR[0].clear();
                weight = 0.0;
                        
                for(it_map = Mymap[0].begin(); it_map != Mymap[0].end(); it_map++)
                {
                        temp_weight =0.0;
                        for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                        {
                                //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0),(*it_map)->P0);
                                temp_weight += probAdjust_mm(0, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                             (1.0 - (double)((*it_map)->R0_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_0 + 0.0000001)) * (*it_map)->P0);
                        }
                                
                        for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++){
                                //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                                temp_weight += probAdjust_mm(0, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                             (1.0 - (double)((*it_map)->R1_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_1 + 0.0000001)) * (*it_map)->P1);
                        }
                        
                        if(temp_weight > weight)
                        {
                                it_map1 = it_map;
                                weight = temp_weight;
                        }
                                
                        TmapRate myMR;
                        myMR.weight = temp_weight;
                        myMR.it_map = it_map;
                        myMR.DFF_id = (*it_map)->DFF_id;
                        MR[0].push_back(myMR);
                }
                
                if(weight == 0.0)
                        break;
                
                gettimeofday(&finish1, NULL);
                t_weight_compute += (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                gettimeofday(&start2, NULL);                
                
                std::sort(MR[0].begin(), MR[0].end(), TrateMapSort);        
                double largest_weight = MR[0][0].weight;
                double smallest_weight = MR[0][0].weight * 0.3;
                const double topK = 0.03;
                double weight_step = (largest_weight - smallest_weight) / 0.05 / MR[0].size();
                
                double cur_weight = largest_weight;
                vector<TmapRate> MR_temp;
                for(j = 0; j < MR[0].size(); j++)
                {
                        if(MR[0][j].weight < cur_weight){
                                MR_temp.push_back(MR[0][j]);
                                cur_weight -= weight_step;
                        }
                }
                
                swap(MR_temp, MR[0]);
                
                for(j = 0; j < MR[0].size(); j++)
                        MR[0][j].weight = 0.0;
                
                assert(j != 0);
                cout << "Top candidate size is " << MR[0].size() << endl;
                
                k = MR[0].size();
                int pos = 0;
                const int tot_thread_num = MR[0].size();
                
                while(k > 0){
                        
                        int thread_num;
                        if(k >= THREAD_NUM_T)
                                thread_num = THREAD_NUM_T;
                        else
                                thread_num = k % THREAD_NUM_T;

                        pthread_t PTs[thread_num];
                        
                        //cout << "thread_num is " << thread_num << endl;
                        for(j = 0; j < thread_num; j++)
                        {
                                for(i=0; i < Ci->flipflopSize(); ++i)
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                        
                                for(i=0; i < selected_traces.size(); ++i)
                                        Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                                //cout << "see" << (*(MR[j].it_map))->DFF_id << endl;
                                Ci->getFlipflop((*(MR[0][pos + j].it_map))->DFF_id)->getOutput(0)->setTraced(true,j);
                        }
                        
                        int seed_num = 0;
                        while(seed_num < 3)
                        {
                                if(selected_traces.size())
                                        initACCMultThread(thread_num, seed_num);
                                else
                                        initMultThread(thread_num);
                                
                                for(j = 0; j < thread_num; j++)
                                {
                                        myWorkarg* mwa= new myWorkarg;
                                        mwa->Tid = j;
                                        mwa->Sim = this;
                                        LoadInitDFFValue(seed_num, j);
                                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                                }
                        
                                for(j = 0; j < thread_num; j++)
                                {
                                        myRetarg* mra = new myRetarg;
                                        pthread_join(PTs[j], (void**) &mra);
                                        
                                        MR[0][pos + mra->Tid].weight += mra->VN;
                                        delete mra;
                                }
                        
                                seed_num++;
                        }
                        
                        k -= thread_num;
                        pos += thread_num;
                }
                
                assert(pos == tot_thread_num);
                std::sort(MR[0].begin(), MR[0].end(), TrateMapSort);
                
                int best_cand = MR[0][0].DFF_id;
                
                gettimeofday(&finish1, NULL);
                t_pick_best += (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start2, NULL);
                assert(best_cand != -1);
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                
                selected_traces.push_back(best_cand);
                
                for(j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);

                //generate ref values
                double VN_bar = 0.0;
                
                int seed_num = 0;
                double cur_VN = 0.0;
                
                while(seed_num < 3){
                                
                        initMultThread(1);
                        LoadInitDFFValue(seed_num, 0);
                        cur_VN += MultCalVNWOLOCK(0);
                        
                        double restime = 0.0;
                        for(j=0; j<Ci->flipflopSize(); ++j)
                        {
                                restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                                Ci->getFlipflop(j)->getOutput(0)->RR_array[0] += restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                        }
                                
                        seed_num++;
                }
                
                for(j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->RR_array[0] /= 3;
                        
                cout << "VN for mode " << assign_file_id << " is "<< cur_VN / 3 <<endl;
                
                for(it_map = Mymap[0].begin();it_map != Mymap[0].end();it_map++){
                        if((*it_map)->DFF_id == best_cand){
                                Mymap[0].erase(it_map);
                                break;
                        }
                }
                        
                VN_bar += cur_VN / 3;
                
                VN_final = VN_bar;
                gettimeofday(&finish1, NULL);
                t_update_RR += (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
        }
        
        gettimeofday(&finish1, NULL);
        
        cout<< "total runtime for Simulation-Based trace selection for one round of the Simulation Anealing is " << trace_size << " is " 
            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //t_pick_best serial
        //t_weight_compute parallelizable
        //t_update_RR parallelizable
        cout << "After parallelization, ideal time for weight computation is " << t_weight_compute << endl;
        cout << "Pick best time is " << t_pick_best << endl;
        cout << "After parallelization, ideal time for update RR is " << t_update_RR << endl;
        
        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        cout<< "seleted signals' outputs names are...." << endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<" ";
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        cout << endl;
        return make_pair(VN_final, 0.0);
}


std::pair<double, double> Simulate::multimodeSASingleMode(const int trace_size, const char* filename)
{
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<TresMap*> *Mymap;
        Mymap = new vector<TresMap*>[assign_file_id];
        
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_RM;
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int>* myTraceSet;
        myTraceSet = new vector<int>[assign_file_id];
        
        vector<int>::iterator it_vec;
        std::pair<double, double> SRR_GRR;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        for(i = 0; i < Ci->signalSize(); ++i) {
                Ci->getSignal(i)->P0_array = new float[assign_file_id];
                Ci->getSignal(i)->P1_array = new float[assign_file_id];
                Ci->getSignal(i)->RR_array = new double[assign_file_id];
        }
        
        double RL_gen_time = 0.0;
        struct timeval start1, finish1, finish2, finish3;
        
        gettimeofday(&start1, NULL);
        readResMap(filename, Mymap, true, -1);
        readMultiSolution(filename, myTraceSet);
        gettimeofday(&finish1, NULL);       
        cout<< "total runtime for reading reachability lists and solutions from different modes is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //------------------------------Simulate Anealing-----------------------------------------
        const int total_mode_num = assign_file_id;
        for(int l = 0; l < total_mode_num; l++){
                assign_file_id = l;
                //random pick an init solution
                int sol_id;
                sol_id = l;//take the first whcih is the current best
                cout << "Take initial solution generated from mode " << sol_id << endl;
                vector<int> selected_traces(myTraceSet[l]);
                vector<int> cur_best_traces(selected_traces);
                
                //set init temperature
                double T = 10000.0;
                double cur_best_SRR = 0.0;// give an initial value
                const double T_min = 1.0;
                const double alpha = 0.95;
                //unsigned int step_size = rand() % 3 + 1;
                unsigned int step_size = 1;
        
                gettimeofday(&start1, NULL);
        
                i = 0;
                while(T > T_min){
                        //randomly pick a step size and randomly kick out traces
                        selected_traces = cur_best_traces;
                        
                        for( j = 0; j < step_size; j++){
                                int temp = rand() % selected_traces.size();
                                selected_traces.erase(selected_traces.begin() + temp);
                        }
                
                        //pick the one with the highest impact weights and add inside
                        pair<double, double> SRR_GRR;
                        SRR_GRR = multimodeSASingleModeProcess(trace_size, Mymap, selected_traces, filename);
                        if(SRR_GRR.first > cur_best_SRR){
                                cur_best_SRR = SRR_GRR.first;
                                swap(cur_best_traces, selected_traces);
                        }
                        else{
                                unsigned int temp = rand() % 65536;
                                double r = (double)temp / 65536.0;
                                double p = (SRR_GRR.first - cur_best_SRR) / T;
                                if(exp(p) > r){
                                        cur_best_SRR = SRR_GRR.first;
                                        swap(cur_best_traces, selected_traces);
                                }
                        }
                
                        T = T * alpha;
                        i++;
                }
        
                gettimeofday(&finish1, NULL);       
                cout << "The number of rounds for doing SA is " << i << endl;
                cout<< "total runtime for Simulate Anealing for mode " << l << " is: "
                    << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
                string str = filename;
                str.erase(str.begin() + str.find("bench"), str.end());
                str += "trace_check_ILP0";
                ofstream out(str.c_str());
                out << cur_best_traces.size() << endl;
                for(i = 0; i < cur_best_traces.size(); i++){
                        cout << Ci->getFlipflop(cur_best_traces[i])->getOutput(0)->getName() << endl;
                        out << Ci->getFlipflop(cur_best_traces[i])->getOutput(0)->getName() << endl;
                }
                
                out << "!" << endl;
                out << "&&&";
                out.close();
                
                //------------------------------Simulate Anealing-----------------------------------------
                SRR_GRR = Check_Traces_SRR_GRR(filename);
                const double init_SRR = SRR_GRR.first;
                cout << "Initial SRR is " << init_SRR << "\t";
                cout << "Initial GRR is " << SRR_GRR.second << endl;
        }
        
        return SRR_GRR;
}


void Simulate::readMultiSolution(string filename, vector<int>* myTraceSet){
        
        int trace_num, flag;
        int cur_size = 0;
        string name;
        
        stringstream ss;
        ss << assign_file_id;
        
        const int MAX_LINE_LENGTH = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        strcpy(line_buffer, "");
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "trace_sol";
        //str += ss.str();        
        //cout << str << endl;
        cout << "Reading multiple-solutions..." << endl;
        
        ifstream in(str.c_str());
        if (!in.is_open()) {
                cerr << "Can't open trace solution file" << endl;
                exit(1);
        }
        
        int mode_cnt = 0;
        while(1){

                in.getline(line_buffer, MAX_LINE_LENGTH);
                
                if(!strcmp(line_buffer, "&&&")){
                        assert(mode_cnt == assign_file_id);
                        break;
                }
                else if(!strcmp(line_buffer, "!")){
                        mode_cnt++;
                }
                else{
                        //cout << "New set of traced flipflops:" << mode_cnt << endl;
                        trace_num = atoi(line_buffer);
                        //assert(trace_num == 8 || trace_num == 16 || trace_num == 32);
                        
                        for(int i = 0; i<Ci->flipflopSize(); ++i)
                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,0);

                        for(int j = 0; j < trace_num; j++){

                                flag = 0;
                                in.getline(line_buffer, MAX_LINE_LENGTH);
                                name = line_buffer;
                                
                                for(int i = 0; i<Ci->flipflopSize(); ++i)
                                {
                                        if(Ci->getFlipflop(i)->getOutput(0)->getName() == name)
                                        {
                                                myTraceSet[mode_cnt].push_back(i);
                                                //cout << name << endl;
                                                flag = 1; break;
                                        }
                                }
                                
                                assert(flag == 1);
                        }                
                }
        }
}


pair<double, double> Simulate::multimodeRef2MergeSelectProcess(const int trace_size,  vector<TresMap*> *Mymap , vector<int> &selected_traces, vector<int> &modes, const char* filename){
        
        int i, j, k;
        double weight, temp_weight;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> *MR;
        MR = new vector<TmapRate>[modes.size()];
        assert(selected_traces.size() == 0);
        
        cout << "file name is " << filename << endl;        
        string tmp = filename;
        tmp += "_report";
        ofstream report(tmp.c_str());
        report<< Ci->flipflopSize() <<endl;
        
        double t_weight_compute = 0.0; //parallelizable
        double t_pick_best = 0.0; //serial
        double t_add_islands = 0.0; //serial
        double t_update_RR = 0.0; //parallelizable
        struct timeval start1, finish1;
        gettimeofday(&start1, NULL);
        
        while(selected_traces.size() < trace_size)
        {
                struct timeval start2, start3, finish2, finish3;
                gettimeofday(&start2, NULL);                
                for(i = 0; i < modes.size(); i++){
                        
                        MR[i].clear();
                        weight = 0.0;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++)
                        {
                                temp_weight =0.0;
                                for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                                {
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0),(*it_map)->P0);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R0_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_0 + 0.0000001)) * (*it_map)->P0);
                                }
                                
                                for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++){
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R1_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_1 + 0.0000001)) * (*it_map)->P1);
                                }
                                
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                                
                                TmapRate myMR;
                                myMR.weight = temp_weight;
                                myMR.it_map = it_map;
                                myMR.DFF_id = (*it_map)->DFF_id;
                                MR[i].push_back(myMR);
                        }
                        
                        if(weight == 0.0)
                                break;
                
                        std::sort(MR[i].begin(), MR[i].end(), TrateMapSort);        
                }
                
                gettimeofday(&finish2, NULL);
                t_weight_compute += (double)(finish2.tv_sec+(finish2.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start3, NULL);
                
                set<int> common;
                set<int>::iterator it_set;

                for(j = 0; j < MR[0].size(); j++){
                        for(k = 0; k < MR[1].size(); k++){
                                if(MR[0][j].DFF_id == MR[1][k].DFF_id)
                                        common.insert(MR[0][j].DFF_id);
                        }
                }
                
                int *scores = new int[common.size()];
                memset(scores, 1, common.size()*sizeof(int));

                int cnt = 0;
                for(it_set = common.begin(); it_set != common.end(); it_set++){
                        for(i = 2; i < modes.size(); i++){
                                for(j = 0; j < MR[i].size(); j++){
                                        if(MR[i][j].DFF_id == *it_set){
                                                scores[cnt]++;
                                                break;
                                        }
                                }
                        }
                        cnt++;
                }

                bool found = false;
                for(j = modes.size() - 1; j > 1; j++){
                        for(i = 0; i < common.size(); i++){
                                if(scores[i] == j){
                                        found = true;
                                        break;
                                }
                        }
                        if(found == true)
                                break;
                }
                
                int best_cand;
                if(found == true){
                        it_set = common.begin();
                        for(k = 0; k < i; k++)
                                it_set++;

                        best_cand = *it_set;
                        cout<<"Chosen flipflop's name in this round is "<<
                                Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                }
                else{
                        cout << "not found using new way!" << endl;
                        //cin.get();
                        
                        vector<TmapRate> MR_;
                        for(i = 0; i < modes.size(); i++){
                                TmapRate myMR;
                                myMR.DFF_id = MR[i][0].DFF_id;
                                myMR.weight = 0.0;
                                MR_.push_back(myMR);
                        }
                        
                        for(int l = 0; l < modes.size(); l++){
                                
                                k = MR_.size();
                                int pos = 0;
                                const int tot_thread_num = k;
                                
                                initSimulate(filename);
                                LoadDFFMap(filename, modes[l]);
                                
                                while(k > 0){
                                        
                                        int thread_num;
                                        if(k >= THREAD_NUM_T)
                                                thread_num = THREAD_NUM_T;
                                        else
                                                thread_num = k % THREAD_NUM_T;

                                        pthread_t PTs[thread_num];
                                        //cout << "thread_num is " << thread_num << endl;
                                        for(j = 0; j < thread_num; j++)
                                        {
                                                for(i=0; i < Ci->flipflopSize(); ++i)
                                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                                                
                                                for(i=0; i < selected_traces.size(); ++i)
                                                        Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);

                                                //cout << "see" << (*(MR[j].it_map))->DFF_id << endl;
                                                Ci->getFlipflop(MR_[pos + j].DFF_id)->getOutput(0)->setTraced(true,j);
                                        }

                                        int seed_num = 0;
                                        while(seed_num < 3)
                                        {
                                                initMultThread(thread_num);
                                                
                                                for(j = 0; j < thread_num; j++)
                                                {
                                                        myWorkarg* mwa= new myWorkarg;
                                                        mwa->Tid = j;
                                                        mwa->Sim = this;
                                                        LoadInitDFFValue(seed_num, j);
                                                        pthread_create(&PTs[j], NULL, work, (void*)mwa);
                                                }
                                        
                                                for(j = 0; j < thread_num; j++)
                                                {
                                                        myRetarg* mra = new myRetarg;
                                                        pthread_join(PTs[j], (void**) &mra);

                                                        MR_[pos + mra->Tid].weight += mra->VN;
                                                        delete mra;
                                                }

                                                seed_num++;
                                        }
                                        
                                        k -= thread_num;
                                        pos += thread_num;
                                }
                        }
                        
                        //assert(pos == tot_thread_num);
                        //cout << "MR_ size is " << MR_.size() << endl;
                        best_cand = MR_[0].DFF_id;
                        if(MR_.size() == 2)
                        {
                                if(MR_[1].weight > MR_[0].weight)
                                        best_cand = MR_[1].DFF_id;
                        }
                        else{
                                std::sort(MR_.begin(), MR_.end(), TrateMapSort);
                                best_cand = MR_[0].DFF_id;
                        }
                        
                        cout << "Chosen flipflop's name in this round is " << Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                }
                
                
                gettimeofday(&finish3, NULL);
                t_pick_best += (double)(finish3.tv_sec+(finish3.tv_usec/1000000.0) - start3.tv_sec+(start3.tv_usec/1000000.0));
                
                gettimeofday(&start2, NULL);
                assert(best_cand != -1);
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                
                selected_traces.push_back(best_cand);
                
                for(j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);

                //generate ref values
                double VN_bar = 0.0;
                for( i = 0; i < modes.size(); i++){
                        
                        initSimulate(filename);
                        LoadDFFMap(filename, modes[i]);
                        
                        int seed_num = 0;
                        double cur_VN = 0.0;
                
                        while(seed_num < 3){
                                
                                initMultThread(1);
                                LoadInitDFFValue(seed_num,0);
                                cur_VN += MultCalVNWOLOCK(0);
                                
                                double restime = 0.0;
                                for(j=0; j<Ci->flipflopSize(); ++j)
                                {
                                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                                        Ci->getFlipflop(j)->getOutput(0)->RR_array[i] += restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                                }
                                
                                seed_num++;
                        }
                
                        for(j=0; j<Ci->flipflopSize(); ++j)
                                Ci->getFlipflop(j)->getOutput(0)->RR_array[i] /= 3;
                        
                        cout << "VN for mode " << i << " is "<< cur_VN / 3 <<endl;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++){
                                if((*it_map)->DFF_id == best_cand){
                                        Mymap[i].erase(it_map);
                                        break;
                                }
                        }
                        
                        if(i == 0)
                                VN_bar = cur_VN / 3;
                }
                
                gettimeofday(&finish2, NULL);
                t_update_RR += (double)(finish2.tv_sec+(finish2.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start3, NULL);
                if(selected_traces.size() == 8)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 8 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        addIslands(selected_traces, VN_bar);
                }
                
                if(selected_traces.size() == 16)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 16 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;
                        
                        addIslands(selected_traces, VN_bar);
                }
                
                //if(selected_traces.size() == 24)
                //addIslands(selected_traces, VN_bar);
                
                if(selected_traces.size() == 32)
                {
                        gettimeofday(&finish1, NULL);
                        
                        cout<< "total runtime for Simulation-Based trace selection when selecting 32 traces is: "
                            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
                        
                        cout<< "seleted signals are...." << endl;
                        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        {
                                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<"\t";
                        }
                        cout<<endl;        
                }
                
                gettimeofday(&finish3, NULL);
                t_add_islands += (double)(finish3.tv_sec+(finish3.tv_usec/1000000.0) - start3.tv_sec+(start3.tv_usec/1000000.0));
        }
        
        gettimeofday(&finish1, NULL);
        
        cout<< "total runtime for Simulation-Based trace selection when selecting " << trace_size << " is " 
            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //t_pick_best serial
        t_weight_compute /= modes.size(); //parallelizable
        t_update_RR /= modes.size(); //parallelizable
        cout << "After parallelization, ideal time for weight computation is " << t_weight_compute << endl;
        cout << "Pick best time is " << t_pick_best << endl;
        cout << "Add islands time is " << t_add_islands << endl;
        cout << "After parallelization, ideal time for update RR is " << t_update_RR << endl;

        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        cout<< "seleted signals' outputs names are...." << endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName()<<endl;
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        
        initMultThread(1);
        LoadInitDFFValue(0,0);
        
        return reportSRR_GRR();
}


pair<double, double> Simulate::multimodeRef2MergeSelect(const int trace_size, const char* filename){
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int> selected_traces;
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        int mode;
        vector<int> modes;

        if(tmp.find("DMA") != string::npos){
                modes.push_back(0);
                modes.push_back(4);
                modes.push_back(5);
                modes.push_back(7);
        }
        else{
                while(1){
                        cout << "Give a mode" << endl;
                        cin >> mode;
                        if(mode == -1)
                                break;
                        modes.push_back(mode);
                }
        }
        
        for(i = 0; i < Ci->signalSize(); ++i) {
                Ci->getSignal(i)->P0_array = new float[modes.size()];
                Ci->getSignal(i)->P1_array = new float[modes.size()];
                Ci->getSignal(i)->RR_array = new double[modes.size()];
        }
        
        vector<TresMap*> *Mymap;
        Mymap = new vector<TresMap*>[modes.size()];
        
        double RL_gen_time = 0.0;
        struct timeval start1, finish1, finish2, finish3;
        
        gettimeofday(&start1, NULL);
        for(i = 0; i < modes.size(); i++){
                assign_file_id = modes[i];
                readResMap(filename, Mymap, false, i);
        }
        gettimeofday(&finish1, NULL);       
        cout<< "total runtime for generating reachability list for different modes is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        RL_gen_time = (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) / assign_file_id;
        cout << "After parallelization, the ideal runtime for RL gen is " << RL_gen_time << endl;
        //---------------------------------------Min------------------------------------------------------
        set<int>::iterator it_RM;
        
        std::pair<double, double> SRR_GRR;
        SRR_GRR = multimodeRef2MergeSelectProcess(trace_size,  Mymap, selected_traces, modes, &filename[0]);
        
        const double init_SRR = SRR_GRR.first;
        cout << "Initial SRR is " << init_SRR << "\t";
        cout << "Initial GRR is " << SRR_GRR.second << endl;
        
        return SRR_GRR;
}                


void Simulate::pickRemovedTracesMerge(vector<int> & selected_traces, list<int>& removedTraces, unsigned int step_size, vector<int> &modes, const char* filename){
        //step_size is currently of no use...
        int i, j, k, l;
        vector<TmapRate> MR;
        vector<TresMap*>::iterator it_map;
        removedTraces.clear();
        
        for(i = 0; i < selected_traces.size(); ++i){
                TmapRate myMR;
                myMR.weight = 0.0;
                myMR.it_map = it_map;
                myMR.DFF_id = selected_traces[i];
                MR.push_back(myMR);
        }
        
        for(l = 0; l < modes.size(); l++){
                
                initSimulate(filename);
                LoadDFFMap(filename, modes[l]);
                
                k = MR.size();
                int pos = 0;
                const int tot_thread_num = MR.size();
                
                while(k > 0){
                        
                        int thread_num;
                        if(k >= THREAD_NUM_T)
                                thread_num = THREAD_NUM_T;
                        else
                                thread_num = k % THREAD_NUM_T;
                        
                        pthread_t PTs[thread_num];
                        
                        //cout << "thread_num is " << thread_num << endl;
                        for(j = 0; j < thread_num; j++)
                        {
                                for(i=0; i < Ci->flipflopSize(); ++i)
                                        Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                                
                                for(i=0; i < selected_traces.size(); ++i)
                                        Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                                Ci->getFlipflop(MR[pos + j].DFF_id)->getOutput(0)->setTraced(false,j);
                        }
                        
                        int seed_num = 0;
                        while(seed_num < 3)
                        {
                                initMultThread(thread_num);
                                
                                myWorkarg* mwa= new myWorkarg[thread_num];
                                for(j = 0; j < thread_num; j++)
                                {
                                        mwa[j].Tid = j;
                                        mwa[j].Sim = this;
                                        LoadInitDFFValue(seed_num, j);
                                        pthread_create(&PTs[j], NULL, work, (void*)(&mwa[j]));
                                }
                        
                                for(j = 0; j < thread_num; j++)
                                {
                                        myRetarg* mra = new myRetarg;
                                        pthread_join(PTs[j], (void**) &mra);
                                        
                                        MR[pos + mra->Tid].weight += mra->VN;
                                        delete mra;
                                }
                                
                                delete [] mwa;
                                seed_num++;
                        }
                        
                        delete [] sigList;
                        delete [] CurSig;        
                                
                        k -= thread_num;
                        pos += thread_num;
                }
                
                assert(pos == tot_thread_num);
        }
        
        std::sort(MR.begin(), MR.end(), TrateMapSort);
        
        for(i = 0; i < MR.size(); i++)
                removedTraces.push_back(MR[i].DFF_id);
}


pair<double, double> Simulate::multimodeSAMergeProcess(const int trace_size, vector<TresMap*> *Mymap, vector<int> &selected_traces, vector<int> &modes, const char* filename){
        
        int i, j, k;
        double weight, temp_weight;
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        vector<int>::iterator it_vec;
        
        vector<TmapRate> *MR;
        MR = new vector<TmapRate>[modes.size()];
        //assert(selected_traces.size() == 0);
        
        cout << "file name is " << filename << endl;        
        //string tmp = filename;
        //tmp += "_report";
        //ofstream report(tmp.c_str());
        //report<< Ci->flipflopSize() <<endl;
        
        double t_weight_compute = 0.0; //parallelizable
        double t_pick_best = 0.0; //serial
        double t_add_islands = 0.0; //serial
        double t_update_RR = 0.0; //parallelizable
        struct timeval start1, start2, finish1, finish2, finish3;
        gettimeofday(&start1, NULL);
        /*
        if(selected_traces.size() != trace_size){
                cout << "Discrepency exists between the existing solution and the required trace size!" << endl;
                cout << "selected trace size is " << selected_traces.size();
                cout << "\trequired trace size is " << trace_size << endl;
        }
        */
        double VN_final;
        while(selected_traces.size() < trace_size)
        {
                gettimeofday(&start2, NULL);                
                for(i = 0; i < modes.size(); i++){
                        
                        MR[i].clear();
                        weight = 0.0;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++)
                        {
                                temp_weight =0.0;
                                for(it_set = (*it_map)->R0_seq.begin(); it_set != (*it_map)->R0_seq.end(); it_set++)
                                {
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0),(*it_map)->P0);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R0_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_0 + 0.0000001)) * (*it_map)->P0);
                                }
                                
                                for(it_set = (*it_map)->R1_seq.begin(); it_set != (*it_map)->R1_seq.end(); it_set++){
                                        //temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), (*it_map)->P1);
                                        temp_weight += probAdjust_mm(i, Ci->getFlipflop(*it_set)->getOutput(0), 
                                                                     (1.0 - (double)((*it_map)->R1_seq_res_len[*it_set]) / (double)((*it_map)->longest_path_length_1 + 0.0000001)) * (*it_map)->P1);
                                }
                                
                                if(temp_weight > weight)
                                {
                                        it_map1 = it_map;
                                        weight = temp_weight;
                                }
                                
                                TmapRate myMR;
                                myMR.weight = temp_weight;
                                myMR.it_map = it_map;
                                myMR.DFF_id = (*it_map)->DFF_id;
                                MR[i].push_back(myMR);
                        }
                        
                        if(weight == 0.0)
                                break;
                
                        std::sort(MR[i].begin(), MR[i].end(), TrateMapSort);        
                }
                
                gettimeofday(&finish1, NULL);
                t_weight_compute += (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                gettimeofday(&start2, NULL);                
                
                vector<TmapRate> MR_t;
                TmapRate myMR;
                
                float *scores = new float[Ci->flipflopSize()]; 
                memset(scores, 0.0, Ci->flipflopSize()*sizeof(float));
                
                for(i = 0; i < modes.size(); i++)
                        for(j = 0; j < MR[i].size(); j++)
                                scores[MR[i][j].DFF_id] += MR[i][j].weight;
                
                for(i = 0; i < Ci->flipflopSize(); i++)
                {
                        myMR.weight = scores[i];
                        myMR.it_map = it_map;
                        myMR.DFF_id = i;
                        MR_t.push_back(myMR);
                }
                std::sort(MR_t.begin(), MR_t.end(), TrateMapSort);        
                
                cout << "Higest impact weight is " << MR_t[0].weight << endl;
                const double topK = 0.03;
                MR_t.resize(floor(MR_t.size() * topK));
                for(j = 0; j < MR_t.size(); j++)
                        MR_t[j].weight = 0.0;
                
                assert(j != 0);
                cout << "Top candidate size is " << MR_t.size() << endl;
                
                for(int l = 0; l < modes.size(); l++){
                        
                        initSimulate(filename);
                        LoadDFFMap(filename, modes[l]);
                        
                        k = MR_t.size();
                        int pos = 0;
                        const int tot_thread_num = MR_t.size();
                
                        while(k > 0){
                        
                                int thread_num;
                                if(k >= THREAD_NUM_T)
                                        thread_num = THREAD_NUM_T;
                                else
                                        thread_num = k % THREAD_NUM_T;
                        
                                pthread_t PTs[thread_num];
                        
                                //cout << "thread_num is " << thread_num << endl;
                                for(j = 0; j < thread_num; j++)
                                {
                                        for(i=0; i < Ci->flipflopSize(); ++i)
                                                Ci->getFlipflop(i)->getOutput(0)->setTraced(false,j);
                                
                                        for(i=0; i < selected_traces.size(); ++i)
                                                Ci->getFlipflop(selected_traces[i])->getOutput(0)->setTraced(true,j);
                                
                                        //cout << "see" << (*(MR[j].it_map))->DFF_id << endl;
                                        Ci->getFlipflop(MR_t[pos + j].DFF_id)->getOutput(0)->setTraced(true,j);
                                }
                        
                                int seed_num = 0;
                                while(seed_num < 3)
                                {
                                        if(selected_traces.size())
                                                initACCMultThread_MM(thread_num, seed_num, l);
                                        else
                                                initMultThread(thread_num);
                                        
                                        myWorkarg* mwa= new myWorkarg[thread_num];
                                        for(j = 0; j < thread_num; j++)
                                        {
                                                mwa[j].Tid = j;
                                                mwa[j].Sim = this;
                                                LoadInitDFFValue(seed_num, j);
                                                pthread_create(&PTs[j], NULL, work, (void*)(&mwa[j]));
                                        }
                                        
                                        for(j = 0; j < thread_num; j++)
                                        {
                                                myRetarg* mra = new myRetarg;
                                                pthread_join(PTs[j], (void**) &mra);
                                                
                                                MR_t[pos + mra->Tid].weight += mra->VN;
                                                delete mra;
                                        }
                                        
                                        delete [] mwa;
                                        seed_num++;        
                                }
                                
                                delete [] sigList;
                                delete [] CurSig;
                                
                                k -= thread_num;
                                pos += thread_num;
                        }
                        assert(pos == tot_thread_num);
                }
                
                std::sort(MR_t.begin(), MR_t.end(), TrateMapSort);
                
                int best_cand = MR_t[0].DFF_id;
                
                gettimeofday(&finish1, NULL);
                t_pick_best += (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
                
                gettimeofday(&start2, NULL);
                assert(best_cand != -1);
                cout<<"Chosen flipflop's name in this round is "<<
                        Ci->getFlipflop(best_cand)->getOutput(0)->getName() << endl;
                
                selected_traces.push_back(best_cand);
                
                for(j=0; j<Ci->flipflopSize(); ++j)
                        Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
                
                for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++)
                        Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);

                //generate ref values
                double VN_bar = 0.0;
                for( i = 0; i < modes.size(); i++){
                        
                        initSimulate(filename);
                        LoadDFFMap(filename, modes[i]);
                        
                        int seed_num = 0;
                        double cur_VN = 0.0;
                
                        while(seed_num < 3){
                                
                                initMultThread(1);
                                LoadInitDFFValue(seed_num,0);
                                cur_VN += MultCalVNWOLOCK(0);
                                
                                for(j = 0; j < Ci->signalSize(); ++j){
                                        Ci->getSignal(j)->Mult_Val0_ref_MM[seed_num][i] = Ci->getSignal(j)->Mult_Val0[0];
                                        Ci->getSignal(j)->Mult_Val1_ref_MM[seed_num][i] = Ci->getSignal(j)->Mult_Val1[0];
                                }
                                
                                double restime = 0.0;
                                for(j = 0; j < Ci->flipflopSize(); ++j)
                                {
                                        restime = Ci->getFlipflop(j)->getOutput(0)->isMultKnown(0);
                                        Ci->getFlipflop(j)->getOutput(0)->RR_array[seed_num] += restime / (TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)));
                                }
                                
                                seed_num++;
                        }
                        
                        for(j=0; j<Ci->flipflopSize(); ++j)
                                Ci->getFlipflop(j)->getOutput(0)->RR_array[i] /= 3;
                        
                        cout << "VN for mode " << i << " is "<< cur_VN / 3 <<endl;
                        
                        for(it_map = Mymap[i].begin();it_map != Mymap[i].end();it_map++){
                                if((*it_map)->DFF_id == best_cand){
                                        Mymap[i].erase(it_map);
                                        break;
                                }
                        }
                        
                        VN_bar += cur_VN / 3;
                }
                
                VN_final = VN_bar;
                gettimeofday(&finish1, NULL);
                t_update_RR += (double)(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start2.tv_sec+(start2.tv_usec/1000000.0));
        }
        
        gettimeofday(&finish1, NULL);
        
        cout<< "total runtime for Simulation-Based trace selection for one round of the Simulation Anealing is " << trace_size << " is " 
            << ( finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //t_pick_best serial
        t_weight_compute /= modes.size(); //parallelizable
        t_update_RR /= modes.size(); //parallelizable
        cout << "After parallelization, ideal time for weight computation is " << t_weight_compute << endl;
        cout << "Pick best time is " << t_pick_best << endl;
        cout << "After parallelization, ideal time for update RR is " << t_update_RR << endl;

        for(int j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        /*
        cout<< "seleted signals' outputs names are...." << endl;
        for(it_vec = selected_traces.begin(); it_vec != selected_traces.end(); it_vec++){
                cout<<Ci->getFlipflop(*it_vec)->getOutput(0)->getName() << " ";
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
                tracedSigs.push_back(Ci->getFlipflop(*it_vec)->getOutput(0));
        }
        cout << endl;
        */
        return make_pair(VN_final, 0.0);
}


std::pair<double, double> Simulate::multimodeSimulateAnealingMerge(const int trace_size, const char* filename)
{
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_RM;
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        int mode;
        vector<int> modes;
        
        if(tmp.find("DMA") != string::npos){
                modes.push_back(0);
                modes.push_back(4);
                modes.push_back(5);
                modes.push_back(7);
        }
        else{
                while(1){
                        cout << "Give a mode" << endl;
                        cin >> mode;
                        if(mode == -1)
                                break;
                        modes.push_back(mode);
                }
        }        
        
        for(i = 0; i < Ci->signalSize(); ++i) {
                Ci->getSignal(i)->P0_array = new float[modes.size()];
                Ci->getSignal(i)->P1_array = new float[modes.size()];
                Ci->getSignal(i)->RR_array = new double[modes.size()];
        }
        
        vector<TresMap*> *Mymap;
        Mymap = new vector<TresMap*>[modes.size()];
        
        //note that assign_file_id is still used in any SA process!!!
        vector<int>* myTraceSet_temp;
        myTraceSet_temp = new vector<int>[assign_file_id];
        vector<vector<int> >myTraceSet;
        
        double RL_gen_time = 0.0;
        struct timeval start1, finish1, finish2, finish3;
        
        gettimeofday(&start1, NULL);
        readMultiSolution(filename, myTraceSet_temp);
        for(i = 0; i < modes.size(); i++){
                assign_file_id = modes[i];
                readResMap(filename, Mymap, false, i);
                myTraceSet.push_back(myTraceSet_temp[modes[i]]);
        }
        gettimeofday(&finish1, NULL);
        cout<< "total runtime for reading reachability lists and solutions from different modes is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        delete[] myTraceSet_temp;
        //------------------------------Simulate Anealing-----------------------------------------
        //random pick an init solution
        int sol_id = -1;
        long RL_size = 0;
        int total_mode_num = modes.size();
        
        long cur_best = 0.0;
        //double* scores = new double[total_mode_num];
        //memset(scores, 0.0, sizeof(double) * total_mode_num);
        //sol_id = 0;//take the first whcih is the current best
        
        for(int l = 0; l < total_mode_num; l++){
                for(it_map = Mymap[l].begin(); it_map != Mymap[l].end(); it_map++)
                        RL_size += (*it_map)->R0_seq.size() + (*it_map)->R1_seq.size();
                
                if(cur_best < ((double)RL_size / (double)total_mode_num)){
                        cur_best = ((double)RL_size / (double)total_mode_num);
                        sol_id = l;
                }
        }
        
        cout << "Take initial solution generated from mode " << modes[sol_id] << endl;
        
        vector<int> selected_traces(myTraceSet[sol_id]);
        vector<int> cur_best_traces(selected_traces);
        vector<int> overall_best_traces(selected_traces);
        
        //set init temperature
        double T = 10000.0;
        double cur_best_SRR = 0.0;// give an initial value
        double overall_best_SRR = 0.0;// give an initial value
        const double T_min = 1.0;
        const double alpha = 0.95;
        //unsigned int step_size = rand() % 3 + 1;
        unsigned int step_size = 1;
        
        gettimeofday(&start1, NULL);
        list<int> ruleout_rank, ruleout_rank_temp;
        //pickRemovedTraces(selected_traces, ruleout_rank, 1, filename);
        
        const int MAX_ITR_CNT = 1000;
        double MAX_RUNTIME;
        const double delta_gap = 8.0;
        
        if(tmp.find("b17") != string::npos || tmp.find("S3") != string::npos)
                MAX_RUNTIME = 2400.0;
        else if(tmp.find("b18") != string::npos || tmp.find("des_perf") != string::npos)
                MAX_RUNTIME = 4800.0;
        else if(tmp.find("dsp") != string::npos || tmp.find("DMA") != string::npos)
                MAX_RUNTIME = 14400.0;//3600.00
        else
                MAX_RUNTIME = 1200.0;
        
        cout << "MAX runtime is " << MAX_RUNTIME << endl;
        
        const int interval = TEST_CASE_NUM * TRACE_DEPTH_NUM * 8 * sizeof(BIT_TYPE);
        for(i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->valArray = new Value[interval];
        
        i = 0;
        bool rand_sel = false;
        while(i < MAX_ITR_CNT){
                cout << "iteration " << i << " step size " << step_size << " rand_sel? " << rand_sel << endl;
                cout << "Temperature is " << T << endl;
                selected_traces = cur_best_traces;
                if(i % 8 == 0)
                        pickRemovedTracesMerge(selected_traces, ruleout_rank, 1, modes, filename);
                ruleout_rank_temp = ruleout_rank;
                assert(selected_traces.size() == ruleout_rank_temp.size());
                
                //select the eliminated traces
                if(rand_sel == false){
                        for(j = 0; j < step_size; j++){
                                int rule_out_trace = ruleout_rank_temp.front();
                                cout << "removed trace is " << Ci->getFlipflop(rule_out_trace)->getOutput(0)->getName() <<endl;
                                it_vec = find(selected_traces.begin(), selected_traces.end(), rule_out_trace);
                                assert(it_vec != selected_traces.end());
                                selected_traces.erase(it_vec);
                                ruleout_rank_temp.pop_front();
                        }
                }
                else{
                        for(j = 0; j < step_size; j++){
                                int temp = rand() % selected_traces.size();
                                selected_traces.erase(selected_traces.begin() + temp);
                                cout << "removed trace is " << Ci->getFlipflop(selected_traces[temp])->getOutput(0)->getName() <<endl;
                                list<int>::iterator it_list;
                                it_list = find(ruleout_rank_temp.begin(), ruleout_rank_temp.end(), selected_traces[temp]);
                                assert(it_list != ruleout_rank_temp.end());
                                ruleout_rank_temp.erase(it_list);
                        }
                }
                
                //pick the one with the highest impact weights and add inside
                pair<double, double> SRR_GRR;
                SRR_GRR = multimodeSAMergeProcess(trace_size, Mymap, selected_traces, modes, filename);
                cout << "SRR of this round " << SRR_GRR.first << "\tCurrent best SRR " << cur_best_SRR << endl;
                if(SRR_GRR.first > cur_best_SRR){
                        cur_best_SRR = SRR_GRR.first;
                        swap(cur_best_traces, selected_traces);
                        
                        if(cur_best_SRR > overall_best_SRR){
                                overall_best_SRR = cur_best_SRR;
                                overall_best_traces = cur_best_traces;
                        }
                        
                        for(j = 0; j < step_size; j++)
                                ruleout_rank_temp.push_back(cur_best_traces.back() - j);
                        
                        step_size = 1;
                        ruleout_rank = ruleout_rank_temp;
                        rand_sel = false;
                        T = T * alpha;
                        cout << "good!" << endl;
                }
                else{
                        unsigned int temp = rand() % 65536;
                        double r = (double)temp / 65536.0;
                        double gap = cur_best_SRR - SRR_GRR.first;
                        double p = (SRR_GRR.first - cur_best_SRR) / T;
                        
                        if(exp(p) > r){
                                cur_best_SRR = SRR_GRR.first;
                                swap(cur_best_traces, selected_traces);
                                
                                for(j = 0; j < step_size; j++)
                                        ruleout_rank_temp.push_back(cur_best_traces.back() - j);
                                
                                ruleout_rank = ruleout_rank_temp;
                                rand_sel = false;
                                T = T * alpha;
                                
                                //if(gap < delta_gap)
                                //step_size++;
                                
                                cout << "good!" << endl;
                        }
                        else{
                                step_size++;
                                cout << "no good!" << endl;
                        }
                }
                
                i++;
                
                if(step_size > 3)
                {
                        step_size = 1;
                        rand_sel = true;
                }
                
                gettimeofday(&finish1, NULL);
                if(finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0) > MAX_RUNTIME)
                        break;
        }
        
        //gettimeofday(&finish1, NULL);
        cout << "The number of rounds for doing SA is " << i << endl;
        cout<< "total runtime for Simulate Anealing is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        cout << "overall best SRR is " << overall_best_SRR <<endl;
        
        for(i=0; i<Ci->flipflopSize(); ++i)
                delete [] Ci->getFlipflop(i)->getOutput(0)->valArray;
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "trace_check_ILP0";
        ofstream out(str.c_str());
        out << overall_best_traces.size() << endl;
        for(i = 0; i < overall_best_traces.size(); i++){
                cout << Ci->getFlipflop(overall_best_traces[i])->getOutput(0)->getName() << " ";
                out << Ci->getFlipflop(overall_best_traces[i])->getOutput(0)->getName() << endl;
        }
        cout << endl;
        out << "!" << endl;
        out << "&&&";
        out.close();
        
        //------------------------------Simulate Anealing-----------------------------------------
        std::pair<double, double> SRR_GRR;
        //cout << "Input total mode num " << endl;
        //cin >> total_mode_num;
        if(str.find("DMA") != string::npos || str.find("dsp") != string::npos)
                total_mode_num = 8;
        else
                total_mode_num = 4;
        
        for(j=0; j<Ci->flipflopSize(); ++j)
                Ci->getFlipflop(j)->getOutput(0)->setTraced(false,0);
        
        for(it_vec = overall_best_traces.begin(); it_vec != overall_best_traces.end(); it_vec++)
                Ci->getFlipflop(*it_vec)->getOutput(0)->setTraced(true,0);
        
        for(i = 0; i < total_mode_num; i++){
                assign_file_id = i;
                
                initSimulate(filename);
                LoadDFFMap(filename, i);
                        
                int seed_num = 0;
                double cur_VN = 0.0;
                
                while(seed_num < 3){
                                
                        initMultThread(1);
                        LoadInitDFFValue(seed_num,0);
                        cur_VN += MultCalVNWOLOCK(0);
                        seed_num++;
                }
                        
                cout << "VN for mode " << i << " is "<< cur_VN / 3 <<endl;
        }
        
        return SRR_GRR;
}


/*Do forward greedy selection using the DATE method or pure
 * Simulation. Then apply the solution on all modes to see the MSRR*/
std::pair<double, double> Simulate::singleModeForwardGreedy(const int trace_size, const char* filename)
{
        
        int i, j, k, flag;
        Value vals[]={Zero,One,Z,X};
        double weight, temp_weight, cur_VN;
        
        vector<TresMap*> *Mymap;
        Mymap = new vector<TresMap*>[assign_file_id];
        
        vector<TresMap*>::iterator it_map;
        vector<TresMap*>::iterator it_map1;
        
        set<int>::iterator it_RM;
        set<int>::iterator it_set;
        set<int>::iterator it_set1;
        
        vector<int>* myTraceSet;
        myTraceSet = new vector<int>[assign_file_id];
        
        vector<int>::iterator it_vec;
        
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "report_biased_1";
        
        for(i = 0; i < Ci->signalSize(); ++i) {
                Ci->getSignal(i)->P0_array = new float[assign_file_id];
                Ci->getSignal(i)->P1_array = new float[assign_file_id];
                Ci->getSignal(i)->RR_array = new double[assign_file_id];
        }
        
        double RL_gen_time = 0.0;
        struct timeval start1, finish1, finish2, finish3;
        
        gettimeofday(&start1, NULL);
        readResMap(filename, Mymap, true, -1);
        gettimeofday(&finish1, NULL);       
        cout<< "total runtime for reading reachability lists and solutions from different modes is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;
        
        //------------------------------Pick which mode-----------------------------------------
        //random pick an init solution
        int sol_id = -1;
        long RL_size = 0;
        const int total_mode_num = assign_file_id;
        
        long cur_best = 0.0;
        //double* scores = new double[total_mode_num];
        //memset(scores, 0.0, sizeof(double) * total_mode_num);
        //sol_id = 0;//take the first whcih is the current best
        
        for(int l = 0; l < total_mode_num; l++){
                for(it_map = Mymap[l].begin(); it_map != Mymap[l].end(); it_map++)
                        RL_size += (*it_map)->R0_seq.size() + (*it_map)->R1_seq.size();
                
                if(cur_best < ((double)RL_size / (double)total_mode_num)){
                        cur_best = ((double)RL_size / (double)total_mode_num);
                        sol_id = l;
                }
        }
        //sol_id = 1;
        cout << "Take mode " << sol_id << " as the target mode..." << endl;
        
        
        //------------------------------Forward greedy slection-----------------------------------------
        assign_file_id = sol_id;
        std::pair<double, double> SRR_GRR;
        
        // two pick one
        
        SRR_GRR = this->biasedSelect(trace_size, filename, 0.0);
        //Write out the solution
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "trace_check_06_25_13_";
        ofstream out(str.c_str());
        out << this->selectedTraces.size() << endl;
        for(i = 0; i < this->selectedTraces.size(); i++){
                cout << Ci->getFlipflop(this->selectedTraces[i])->getOutput(0)->getName() << " ";
                out << Ci->getFlipflop(this->selectedTraces[i])->getOutput(0)->getName() << endl;
        }
        cout << endl;
        out << "!" << endl;
        out << "&&&";
        out.close();
        
        /*
        SRR_GRR = this->simSelect(trace_size, filename);
        //Write out the solution
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "trace_check_06_25_13";
        ofstream out(str.c_str());
        out << this->tracedSigs.size() << endl;
        for(i = 0; i < this->tracedSigs.size(); i++){
                cout << this->tracedSigs[i]->getName() << " ";
                out << this->tracedSigs[i]->getName() << endl;
        }
        cout << endl;
        out << "!" << endl;
        out << "&&&";
        out.close();
        */
        
        //Check the SRR for multimodes
        for(i = 0; i < total_mode_num; i++){
                assign_file_id = i;
                SRR_GRR = this->Check_Traces_SRR_GRR(filename);
                const double init_SRR = SRR_GRR.first;
                cout << "Initial SRR is " << init_SRR << "\t";
                cout << "Initial GRR is " << SRR_GRR.second << endl;
        }
        
        return SRR_GRR;
}



/*-----------------------------Switching Activity Experiments-------------------------------------
**************************************************************************************************/

bool Simulate::SW_EXPR_DFS_Forward(Node* ni, const int DFF_id, set<Node*>& PassedNodes)
{
        for(int i = 0; i < ni->outputSize(); i++)
        {
                for(int j = 0; j < ni->getOutput(i)->outputSize(); j++)
                {
                        if(ni->getOutput(i)->getOutput(j)->visited == true)
                                continue;
                        
                        if(ni->getOutput(i)->getOutput(j)->signature() == FLIPFLOP)
                        {
                                if(((FlipflopNode*)ni->getOutput(i)->getOutput(j))->FF_index == DFF_id)
                                        continue;
                                
                                if(std::find(Ci->getFlipflop(DFF_id)->nearbyDFFs.begin(), 
                                             Ci->getFlipflop(DFF_id)->nearbyDFFs.end(), 
                                             ((FlipflopNode*)ni->getOutput(i)->getOutput(j))->FF_index) == Ci->getFlipflop(DFF_id)->nearbyDFFs.end())
                                        Ci->getFlipflop(DFF_id)->nearbyDFFs.push_back(((FlipflopNode*)ni->getOutput(i)->getOutput(j))->FF_index);
                        }
                        else
                        {
                                ni->getOutput(i)->getOutput(j)->visited = true;
                                PassedNodes.insert(ni->getOutput(i)->getOutput(j));
                                SW_EXPR_DFS_Forward(ni->getOutput(i)->getOutput(j), DFF_id, PassedNodes);
                        }
                }        
        }
        
        return true;
}


void Simulate::SW_EXPR_DFS_Backtrack(const int cur_DFF_id)
{
        queue<Node*> tmp_Nodes;
        for(int i = 0; i < Ci->getFlipflop(cur_DFF_id)->getInput(1)->inputSize(); i++)
                tmp_Nodes.push(Ci->getFlipflop(cur_DFF_id)->getInput(1)->getInput(i));
        
        while(!tmp_Nodes.empty()){
                Node* N_front = tmp_Nodes.front();
                for(int i = 0; i < N_front->inputSize(); i++){
                        for(int j = 0; j < N_front->getInput(i)->inputSize(); j++){
                                Node* N_new = N_front->getInput(i)->getInput(j);
                                if(N_new->signature() == FLIPFLOP)
                                        continue;
                                
                                if(Ci->getFlipflop(cur_DFF_id)->cone_nodes.find(N_new) == Ci->getFlipflop(cur_DFF_id)->cone_nodes.end()){
                                        Ci->getFlipflop(cur_DFF_id)->cone_nodes.insert(N_new);
                                        tmp_Nodes.push(N_new);
                                }
                        }
                }
                
                tmp_Nodes.pop();
        }
}


bool Simulate::SWActivityGen(string filename, const int set_cnt)
{
        srand ( time(NULL) );
        vector<Signal*> vn;
        long total_vn_cnt = 0;
        int n, count_traced; long st;
        
        stringstream ss;
        ss << assign_file_id;
        
        //init before assign
        initSimulate(filename);
        initMultThread(1);
        
        //parsing the assign file
        string tmp = filename;
        tmp.erase(tmp.begin() + tmp.find("bench"), tmp.end());
        tmp += "assign_";
        tmp += ss.str();
        cout << "Assign filename is " << tmp << endl;
        
        ifstream in_assign(tmp.c_str());
        if(!in_assign.is_open()){
                cout << "Open assign file failed!" << endl;
                exit(1);
        }
        
        int data, flag; char pin_name[50];
        map<string, int> ctrSigMap;
        const int MAX_LINE_LENGTH  = 65536;
        char line_buffer[MAX_LINE_LENGTH];
        
        while(!in_assign.eof()){
                flag = 0;
                in_assign.getline(line_buffer, MAX_LINE_LENGTH);
                sscanf (line_buffer, "%s\t%d", pin_name, &data);
                tmp = pin_name;
                ctrSigMap[tmp] = data;
                cout << "pin is " << tmp;
                for(int i=0; i<Ci->signalSize(); ++i){
                        if(Ci->getSignal(i)->getName() == tmp){
                                flag = 1;
                                cout << "\tvalue is " << data << endl;
                                Ci->getSignal(i)->untouchible = true;
                                break;
                        }
                }
                
                assert(flag == 1);
        }
        
        //random input pattern generation
        for(int i=0; i<Ci->flipflopSize(); ++i)
                Ci->getFlipflop(i)->getOutput(0)->valArray = new Value[SIM_CYCLE_NUM];
                
        for(int i=0; i<Ci->gateSize(); ++i)
                Ci->getGate(i)->weight = 0.0;
        
        myDataType f,g;
        for(int i=0; i<Ci->flipflopSize(); ++i){
                //note that already is "z", just change mul_val1 to 0 at
                //the first cycle is ok
                f.assign((BIT_TYPE)1);
                for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)) - 1; k++)
                        f = f << 1;
                Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[0] = (Ci->getFlipflop(i)->getOutput(0)->Mult_Val1[0] ^ f);
        }

        for(int i=0; i<Ci->inputSize(); ++i){
                if(Ci->getInput(i)->getInput(0)->untouchible == true){
                        if(ctrSigMap[Ci->getInput(i)->getInput(0)->getName()] == 1){
                                f.assign((BIT_TYPE)1);
                                g = f;
                                for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); k++)
                                {
                                        f = f << 1;
                                        f = f | g;
                                }
                                
                                Ci->getInput(i)->getInput(0)->Mult_Val0[0] = f;
                                Ci->getInput(i)->getInput(0)->Mult_Val1[0] = f;
                        }
                        else{
                                Ci->getInput(i)->getInput(0)->Mult_Val0[0].assign((BIT_TYPE)0);
                                Ci->getInput(i)->getInput(0)->Mult_Val1[0].assign((BIT_TYPE)0);
                        }
                }
                else{
                        for(int k = 0; k < TRACE_DEPTH_NUM * (8 * sizeof(BIT_TYPE)); k++){
                                
                                int val = rand()%2;
                                myDataType temp0, temp1;
                                
                                temp0 = Ci->getInput(i)->getInput(0)->Mult_Val0[0];
                                temp1 = Ci->getInput(i)->getInput(0)->Mult_Val1[0];
                                
                                if(val == 0){
                                        Ci->getInput(i)->getInput(0)->Mult_Val0[0] = (Ci->getInput(i)->getInput(0)->Mult_Val0[0] << 1);
                                        Ci->getInput(i)->getInput(0)->Mult_Val1[0] = (Ci->getInput(i)->getInput(0)->Mult_Val1[0] << 1);
                                }
                                else{
                                        f.assign((BIT_TYPE)1);
                                        Ci->getInput(i)->getInput(0)->Mult_Val0[0] = (Ci->getInput(i)->getInput(0)->Mult_Val0[0] << 1);
                                        Ci->getInput(i)->getInput(0)->Mult_Val0[0] = (Ci->getInput(i)->getInput(0)->Mult_Val0[0] | f);
                                        Ci->getInput(i)->getInput(0)->Mult_Val1[0] = (Ci->getInput(i)->getInput(0)->Mult_Val1[0] << 1);
                                        Ci->getInput(i)->getInput(0)->Mult_Val1[0] = (Ci->getInput(i)->getInput(0)->Mult_Val1[0] | f);
                                }
                        }
                }
        }

        //the actual restoration
        sigList[0].SL.clear();
        for(int i=0; i<Ci->inputSize(); ++i)
                sigList[0].SL.push_back(Ci->getInput(i)->getInput(0));
        
        for(int i=0; i<Ci->flipflopSize(); ++i)
                sigList[0].SL.push_back(Ci->getFlipflop(i)->getOutput(0));
        
        while (!sigList[0].SL.empty())
        {
                CurSig[0] = sigList[0].SL.front();
                sigList[0].SL.erase(sigList[0].SL.begin());
                
#ifdef DEBUG_SIMULATE      
                        cout<<"Current signals in list are"<<endl;
                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); it!=sigList[0].SL.end(); ++it)
                                cout<<(*it)->getName()<<"\t";
                        cout<<endl;
                        
                        PrintSignalBitVal(CurSig[0], 0);
                        cin.get();
#endif

                if(CurSig[0]->outputSize()!=0){
                        if(CurSig[0]->getOutput(0)->signature()!=INPUT){
                                for(int i=0; i<CurSig[0]->outputSize(); ++i){
                                        
                                        if(CurSig[0]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getOutput(i)->setBitOutput(0) == false)
                                                        continue;
                                                
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                //if(!listed && CurSig[0]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                if(!listed)
                                                        sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(0));
                                                
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getOutput(i)->isBitActive(0)){
                                                for(int j=0; j<CurSig[0]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        //if(!listed && CurSig[0]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b') 
                                                        if(!listed)
                                                                sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                        else{
                                
                                for(int i=1; i<CurSig[0]->outputSize(); ++i){
                                        
                                        if(CurSig[0]->getOutput(i)->signature()==FLIPFLOP){
                                                if(CurSig[0]->getOutput(i)->setBitOutput(0) == false)
                                                        continue;
                                                bool listed = false;
                                                for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                        if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(0)->getName())
                                                                listed = true;
                                                }
                                                //if(!listed && CurSig[0]->getOutput(i)->getOutput(0)->getName().c_str()[0] != 'b') 
                                                if(!listed)
                                                        sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(0));
                                                continue;
                                        }
                                        
                                        if(CurSig[0]->getOutput(i)->isBitActive(0)){
                                                for(int j=0; j<CurSig[0]->getOutput(i)->outputSize(); ++j){
                                                        bool listed = false;
                                                        for(list<Signal*>::iterator it=sigList[0].SL.begin(); (it!=sigList[0].SL.end()) && (!listed); ++it){
                                                                if((*it)->getName()== CurSig[0]->getOutput(i)->getOutput(j)->getName())
                                                                        listed = true;
                                                        }
                                                        //if(!listed && CurSig[0]->getOutput(i)->getOutput(j)->getName().c_str()[0] != 'b' )
                                                        if(!listed)
                                                                sigList[0].SL.push_back(CurSig[0]->getOutput(i)->getOutput(j));
                                                }
                                        }
                                }
                        }
                }
        }
        
        cout << "Finishing simulation..." << endl;
        
        int pre_val, cur_val;
        assert(TRACE_DEPTH_NUM * 8 * sizeof(BIT_TYPE) == SIM_CYCLE_NUM);
        
        const int bit_num = 8 * sizeof(BIT_TYPE);
        for(int k = 0; k < Ci->signalSize(); ++k){
                long count_x = 0;
                long cycle_count = 0;
                Signal* sig = Ci->getSignal(k);
                //cout<<"For signal "<<sig->getName()<<endl;
                
                int tmp_set_cnt = 0;
                for(int i = 0; i < TRACE_DEPTH_NUM; i++)
                {
                        sig->weight = 0.0;
                        for(int j = 0; j < 8 * sizeof(BIT_TYPE); j++)
                        {
                                BIT_TYPE temp1 = sig->Mult_Val0[0].bits[i];
                                BIT_TYPE temp2 = sig->Mult_Val1[0].bits[i];
                                
                                temp1 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                                temp1 >>= bit_num - 1 - j;
                                
                                temp2 &= ((BIT_TYPE)1 << (bit_num - 1 - j));
                                temp2 >>= bit_num - 1 - j;
                                
                                if(temp1 == temp2){
                                        cur_val = (int)temp1;
                                        
                                        if(cur_val == 0)
                                                sig->setFlag0(sig->getFlag0()+1);
                                        else
                                                sig->setFlag1(sig->getFlag1()+1);
                                        
                                        if(i !=0 && j!=0){
                                                if(pre_val != cur_val && sig->inputSize())
                                                        sig->weight += 1.0;
                                        }
                                        
                                        //cout<<temp1;
                                }
                                else{
                                        cur_val = 2;
                                        count_x++;
                                        //cout<<"X";
                                }
                                
                                if(sig->inputSize() && sig->getInput(0)->signature() == FLIPFLOP)
                                        sig->valArray[cycle_count++] = (Value)(cur_val);
                                
                                pre_val = cur_val;
                        }
                        
                        if(tmp_set_cnt != set_cnt)
                                sig->SW[tmp_set_cnt++] = sig->weight / 8 / sizeof(BIT_TYPE);
                }
                
                //assert(count_x < 100);
        }
        
        for(int i=0; i<Ci->signalSize(); ++i){
                Ci->getSignal(i)->setP0( ((float)Ci->getSignal(i)->getFlag0()) / SIM_CYCLE_NUM);
                Ci->getSignal(i)->setP1( ((float)Ci->getSignal(i)->getFlag1()) / SIM_CYCLE_NUM);
        }
        
        /*If write to file*/
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "sw_";
        str += ss.str();
        cout << "Output switching activity filename is " << str << endl;
        
        ofstream out(str.c_str());
        for(int k = 0; k < Ci->signalSize(); ++k){
                out << Ci->getSignal(k)->getName() << "\t";
                for(int i = 0; i < set_cnt; ++i)
                        out << Ci->getSignal(k)->SW[i] << "\t";
                
                //if(k < Ci->signalSize() - 1)//convenient for read
                out << endl;
        }
        out.close();
        
        cout << "Done!" << endl;
        return true;
}


bool Simulate::SWActivityRead(string filename, const int set_cnt){
        
        int i,k;
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "sw_";

        stringstream ss;
        ss << assign_file_id;
        
        str += ss.str();
        cout << "Input switching activity filename is " << str << endl;
        
        ifstream inFile(str.c_str());
        while(!inFile.eof()){
                string sigName;
                inFile >> sigName;
                for(k = 0; k < Ci->signalSize(); ++k){
                        if(Ci->getSignal(k)->getName() == sigName)
                                break;
                }
                
                if(k == Ci->signalSize())
                        break;
                
                for(i = 0; i < set_cnt; i++){
                        inFile >> Ci->getSignal(k)->SW[i];
                        //cout << Ci->getSignal(k)->SW[i] << "\t";
                }
                //cout << endl;
                //inFile.ignore(65536, '\n');
        }
        
        inFile.close();
        return true;
}


double correlationCompute(double* x, double* y, const int len){        
        double ex = 0.0, ey = 0.0, xt, yt;
        double sxx = 0.0, syy = 0.0, sxy = 0.0;
        const double TINY_VALUE = 1e-20;

        for (int i = 0; i < len; i++) {
                ex += x[i];
                ey += y[i];
        }
        
        if(ex < 0.000001)
                return -1000.0;
        
        ex /= len;
        ey /= len;
        
        for (int i = 0; i < len; i++) {
                xt = x[i] - ex;
                yt = y[i] - ey;
                sxx += xt * xt;
                syy += yt * yt;
                sxy += xt * yt;
        }
        
        double temp = sxx * syy;
        
        //if(temp < 0.000001)
        //temp = 0.0;
        //else{
        temp = sqrt(temp);
        //assert(temp >= 0.001);
        //}
        
        int sign = (sxy >= 0.0) ? 1 : -1;
        temp = sxy / (temp + TINY_VALUE);
        
        if(fabs(temp) > 1.0)
                return sign * 1.0;
        else
                return temp;
}


double Simulate::SW_EXPR_Trace_Selection(const int trace_size, const char* filename){
        
        for(int i = 0; i < Ci->gateSize(); ++i)
                Ci->getGate(i)->visited = false;
                
        cout << "Creating graph and edge computation..." << endl;
        for(int i = 0; i < Ci->flipflopSize(); ++i)
        {
                set<Node*> PassedNodes;
                set<Node*>::iterator it;
                SW_EXPR_DFS_Forward(Ci->getFlipflop(i), i, PassedNodes);
                for(int j = 0; j < Ci->getFlipflop(i)->nearbyDFFs.size(); j++){
                        int end_dff_id = Ci->getFlipflop(i)->nearbyDFFs[j];
                        Ci->getFlipflop(end_dff_id)->backDFFs.push_back(i);
                }
                
                for(it = PassedNodes.begin(); it != PassedNodes.end(); it++)
                        (*it)->visited = false;
        }
        
        for(int i = 0; i < Ci->flipflopSize(); ++i)
                SW_EXPR_DFS_Backtrack(i);
        
        cout << "Creating graph and edge computation finished..." << endl;       
        cout << "Switching Activity Gen Starts..." << endl;
        
        const int set_cnt = 30;
        const int cycle_interval = 8 * sizeof(BIT_TYPE); //64 
        assert(cycle_interval * set_cnt < SIM_CYCLE_NUM);
        
        for(int i = 0; i < Ci->signalSize(); ++i)
                Ci->getSignal(i)->SW = new double[set_cnt];        
        
        string tmp_file_name = filename;
        //SWActivityGen(tmp_file_name, set_cnt);
        SWActivityRead(tmp_file_name, set_cnt);
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "sw_expr_report_r_";

        stringstream ss;
        ss << assign_file_id;
        str += ss.str();
        
        ofstream out(str.c_str());
        double total_bias = 0.0;
        long effect_DFF_cnt = 0;
        for(int i = 0; i < Ci->flipflopSize(); ++i){
                out << Ci->getFlipflop(i)->getOutput(0)->getName() << "\t" << Ci->getFlipflop(i)->cone_nodes.size() << endl;;
                double avg_sw[set_cnt];
                memset(avg_sw, 0.0, sizeof(double) * set_cnt);
                
                for(int j = 0; j < set_cnt; j++){
                        set<Node*>::iterator it_set;
                        for(it_set = Ci->getFlipflop(i)->cone_nodes.begin(); it_set != Ci->getFlipflop(i)->cone_nodes.end(); it_set++)
                                avg_sw[j] += (*it_set)->getOutput(0)->SW[j];
                        
                        if(Ci->getFlipflop(i)->cone_nodes.size())
                                avg_sw[j] /= Ci->getFlipflop(i)->cone_nodes.size();
                }
                
                for(int j = 0; j < set_cnt; j++){
                        out << Ci->getFlipflop(i)->getOutput(0)->SW[j] << "\t" << avg_sw[j] << "\t";
                        for(int k = 0; k < Ci->getFlipflop(i)->backDFFs.size(); k++){
                                int back_DFF_id = Ci->getFlipflop(i)->backDFFs[k];
                                //out << Ci->getFlipflop(back_DFF_id)->getOutput(0)->getName() << "\t";
                                out << Ci->getFlipflop(back_DFF_id)->getOutput(0)->SW[j] << "\t";
                        }
                        out << endl;
                }
                
                double temp = correlationCompute(Ci->getFlipflop(i)->getOutput(0)->SW, &avg_sw[0], set_cnt);
                if(temp != -1000.0){
                        effect_DFF_cnt++;
                        total_bias += temp;
                }
        }
        
        cout << "Average corellation-coefficient is " << total_bias / effect_DFF_cnt << endl;
        out.close();
        return 0.0;
}





